home *** CD-ROM | disk | FTP | other *** search
/ Game Programming in C++ - Start to Finish / GameProgrammingS.iso / developer_install / CEGUISDK-0.4.1-VC6-STLport.exe / {app} / include / CEGUIString.h < prev    next >
Encoding:
C/C++ Source or Header  |  2005-11-08  |  148.4 KB  |  5,576 lines

  1. /************************************************************************
  2.     filename:     CEGUIString.h
  3.     created:    26/2/2004
  4.     author:        Paul D Turner
  5.     
  6.     purpose:    Defines string class used within the GUI system.
  7. *************************************************************************/
  8. /*************************************************************************
  9.     Crazy Eddie's GUI System (http://www.cegui.org.uk)
  10.     Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
  11.  
  12.     This library is free software; you can redistribute it and/or
  13.     modify it under the terms of the GNU Lesser General Public
  14.     License as published by the Free Software Foundation; either
  15.     version 2.1 of the License, or (at your option) any later version.
  16.  
  17.     This library is distributed in the hope that it will be useful,
  18.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  20.     Lesser General Public License for more details.
  21.  
  22.     You should have received a copy of the GNU Lesser General Public
  23.     License along with this library; if not, write to the Free Software
  24.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  25. *************************************************************************/
  26. #ifndef _CEGUIString_h_
  27. #define _CEGUIString_h_
  28.  
  29. #include "CEGUIBase.h"
  30. #include <string>
  31. #include <string.h>
  32. #include <stdexcept>
  33.  
  34. // Start of CEGUI namespace section
  35. namespace CEGUI
  36. {
  37. #define STR_QUICKBUFF_SIZE    32
  38.     /*************************************************************************
  39.         Basic Types
  40.     *************************************************************************/
  41.     typedef        uint8    utf8;
  42.     //typedef        uint16    utf16;  // removed typedef to prevent usage, as utf16 is not supported (yet)
  43.     typedef        uint32    utf32;
  44.  
  45. /*!
  46. \brief
  47.     String class used within the GUI system.
  48.  
  49.     For the most part, this class can replace std::string in basic usage.  However, currently String does not use the
  50.     current locale, and also comparisons do not take into account the Unicode data tables, so are not 'correct'
  51.     as such.
  52. */
  53. class CEGUIEXPORT String
  54. {
  55. public:
  56.     /*************************************************************************
  57.         Integral Types
  58.     *************************************************************************/
  59.     typedef        utf32            value_type;                    //!< Basic 'code point' type used for String (utf32)
  60.     typedef        size_t            size_type;                    //!< Unsigned type used for size values and indices
  61.     typedef        ptrdiff_t        difference_type;            //!< Signed type used for differences
  62.     typedef        utf32&            reference;                    //!< Type used for utf32 code point references
  63.     typedef        const utf32&    const_reference;            //!< Type used for constant utf32 code point references
  64.     typedef        utf32*            pointer;                    //!< Type used for utf32 code point pointers
  65.     typedef        const utf32*    const_pointer;                //!< Type used for constant utf32 code point pointers
  66.  
  67.     static const size_type        npos;                        //!< Value used to represent 'not found' conditions and 'all code points' etc.
  68.  
  69. private:
  70.     /*************************************************************************
  71.         Implementation data
  72.     *************************************************************************/
  73.     size_type    d_cplength;            //!< holds length of string in code points (not including null termination)
  74.     size_type    d_reserve;            //!< code point reserve size (currently allocated buffer size in code points).
  75.  
  76.     mutable utf8*        d_encodedbuff;        //!< holds string data encoded as utf8 (generated only by calls to c_str() and data())
  77.     mutable size_type    d_encodeddatlen;    //!< holds length of encoded data (in case it's smaller than buffer).
  78.     mutable size_type    d_encodedbufflen;    //!< length of above buffer (since buffer can be bigger then the data it holds to save re-allocations).
  79.  
  80.     utf32        d_quickbuff[STR_QUICKBUFF_SIZE];    //!< This is a integrated 'quick' buffer to save allocations for smallish strings
  81.     utf32*        d_buffer;                            //!< Pointer the the main buffer memory.  This is only valid when quick-buffer is not being used
  82.  
  83. public:
  84.     /*************************************************************************
  85.         Iterator Classes
  86.     *************************************************************************/
  87.     /*!
  88.     \brief
  89.         Constant forward iterator class for String objects
  90.     */
  91. #if defined(_MSC_VER) && (_MSC_VER <= 1200)
  92.     class const_iterator : public std::iterator<std::random_access_iterator_tag, utf32>
  93. #else
  94.     class const_iterator : public std::iterator<std::random_access_iterator_tag, utf32, std::ptrdiff_t, const utf32*, const utf32&>
  95. #endif
  96.     {
  97.  
  98.     public:
  99.         //////////////////////////////////////////////////////////////////////////
  100.         // data
  101.         //////////////////////////////////////////////////////////////////////////
  102.         const utf32*    d_ptr;
  103.  
  104.  
  105.         //////////////////////////////////////////////////////////////////////////
  106.         // Methods
  107.         //////////////////////////////////////////////////////////////////////////
  108.         const_iterator(void)
  109.         {
  110.             d_ptr = 0;
  111.         }
  112.         const_iterator(const_pointer ptr)
  113.         {
  114.             d_ptr = ptr;
  115.         }
  116.  
  117.         const_reference    operator*() const
  118.         {
  119.             return *d_ptr;
  120.         }
  121.  
  122. #if defined(_MSC_VER) && (_MSC_VER <= 1200)
  123. #    pragma warning (push)
  124. #    pragma warning (disable : 4284)
  125. #endif
  126.         const_pointer    operator->() const        
  127.         {
  128.             return &**this;
  129.         }
  130.  
  131. #if defined(_MSC_VER) && (_MSC_VER <= 1200)
  132. #    pragma warning (pop)
  133. #endif
  134.  
  135.         const_iterator&    operator++()
  136.         {
  137.             ++d_ptr;
  138.             return *this;
  139.         }
  140.  
  141.         const_iterator    operator++(int)        
  142.         {
  143.             const_iterator temp = *this;
  144.             ++*this;
  145.             return temp;
  146.         }
  147.  
  148.         const_iterator&    operator--()
  149.         {
  150.             --d_ptr;
  151.             return *this;
  152.         }
  153.  
  154.         const_iterator    operator--(int)        
  155.         {
  156.             const_iterator temp = *this;
  157.             --*this;
  158.             return temp;
  159.         }
  160.  
  161.         const_iterator& operator+=(difference_type offset)
  162.         {
  163.             d_ptr += offset;
  164.             return *this;
  165.         }
  166.  
  167.         const_iterator operator+(difference_type offset) const
  168.         {
  169.             const_iterator temp = *this;
  170.             return temp += offset;
  171.         }
  172.  
  173.         const_iterator& operator-=(difference_type offset)
  174.         {
  175.             return *this += -offset;
  176.         }
  177.  
  178.         const_iterator operator-(difference_type offset) const
  179.         {
  180.             const_iterator temp = *this;
  181.             return temp -= offset;
  182.         }
  183.  
  184.         difference_type operator-(const const_iterator& iter) const
  185.         {
  186.             return d_ptr - iter.d_ptr;
  187.         }
  188.  
  189.         const_reference operator[](difference_type offset) const
  190.         {
  191.             return *(*this + offset);
  192.         }
  193.  
  194.         bool operator==(const const_iterator& iter) const
  195.         {
  196.             return d_ptr == iter.d_ptr;
  197.         }
  198.  
  199.         bool operator!=(const const_iterator& iter) const
  200.         {
  201.             return !(*this == iter);
  202.         }
  203.  
  204.         bool operator<(const const_iterator& iter) const
  205.         {
  206.             return d_ptr < iter.d_ptr;
  207.         }
  208.  
  209.         bool operator>(const const_iterator& iter) const
  210.         {
  211.             return (!(iter < *this));
  212.         }
  213.  
  214.         bool operator<=(const const_iterator& iter) const
  215.         {
  216.             return (!(iter < *this));
  217.         }
  218.  
  219.         bool operator>=(const const_iterator& iter) const
  220.         {
  221.             return (!(*this < iter));
  222.         }
  223.  
  224.         friend const_iterator operator+(difference_type offset, const const_iterator& iter)
  225.         {
  226.             return iter + offset;
  227.         }
  228.  
  229.     };
  230.  
  231.     /*!
  232.     \brief
  233.         Forward iterator class for String objects
  234.     */
  235.     class iterator : public const_iterator
  236.     {
  237.     public:
  238.         iterator(void) {}
  239.         iterator(pointer ptr) : const_iterator(ptr) {}
  240.  
  241.  
  242.         reference operator*() const
  243.         {
  244.             return ((reference)**(const_iterator *)this);
  245.         }
  246.  
  247. #if defined(_MSC_VER) && (_MSC_VER <= 1200)
  248. #    pragma warning (push)
  249. #    pragma warning (disable : 4284)
  250. #endif
  251.  
  252.         pointer operator->() const
  253.         {
  254.             return &**this;
  255.         }
  256.  
  257. #if defined(_MSC_VER) && (_MSC_VER <= 1200)
  258. #    pragma warning (pop)
  259. #endif
  260.  
  261.         iterator& operator++()
  262.         {
  263.             ++this->d_ptr;
  264.             return *this;
  265.         }
  266.  
  267.         iterator operator++(int)
  268.         {
  269.             iterator temp = *this;
  270.             ++*this;
  271.             return temp;
  272.         }
  273.  
  274.         iterator& operator--()
  275.         {
  276.             --this->d_ptr;
  277.             return *this;
  278.         }
  279.  
  280.         iterator operator--(int)
  281.         {
  282.             iterator temp = *this;
  283.             --*this;
  284.             return temp;
  285.         }
  286.  
  287.         iterator& operator+=(difference_type offset)
  288.         {
  289.             this->d_ptr += offset;
  290.             return *this;
  291.         }
  292.  
  293.         iterator operator+(difference_type offset) const
  294.         {
  295.             iterator temp = *this;
  296.             return temp + offset;
  297.         }
  298.  
  299.         iterator& operator-=(difference_type offset)
  300.         {
  301.             return *this += -offset;
  302.         }
  303.  
  304.         iterator operator-(difference_type offset) const
  305.         {
  306.             iterator temp = *this;
  307.             return temp -= offset;
  308.         }
  309.  
  310.         difference_type operator-(const const_iterator& iter) const
  311.         {
  312.             return ((const_iterator)*this - iter);
  313.         }
  314.  
  315.         reference operator[](difference_type offset) const
  316.         {
  317.             return *(*this + offset);
  318.         }
  319.  
  320.         friend iterator operator+(difference_type offset, const iterator& iter)
  321.         {
  322.             return iter + offset;
  323.         }
  324.  
  325.     };
  326.  
  327.     /*!
  328.     \brief
  329.         Constant reverse iterator class for String objects
  330.     */
  331. #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
  332.     typedef    std::reverse_iterator<const_iterator, const_pointer, const_reference, difference_type>    const_reverse_iterator;
  333. #else
  334.     typedef    std::reverse_iterator<const_iterator>    const_reverse_iterator;
  335. #endif
  336.  
  337.     /*!
  338.     \brief
  339.         Reverse iterator class for String objects
  340.     */
  341. #if defined(_MSC_VER) && ((_MSC_VER <= 1200) || ((_MSC_VER <= 1300) && defined(_STLPORT_VERSION)))
  342.     typedef std::reverse_iterator<iterator, pointer, reference, difference_type>            reverse_iterator;
  343. #else
  344.     typedef std::reverse_iterator<iterator>            reverse_iterator;
  345. #endif
  346.  
  347. public:
  348.     //////////////////////////////////////////////////////////////////////////
  349.     // Default Construction and Destructor
  350.     //////////////////////////////////////////////////////////////////////////
  351.     /*!
  352.     \brief
  353.         Constructs an empty string
  354.     */
  355.     String(void)
  356.     {
  357.         init();
  358.     }
  359.  
  360.     /*!
  361.     \brief
  362.         Destructor for String objects
  363.     */
  364.     ~String(void);
  365.  
  366.     //////////////////////////////////////////////////////////////////////////
  367.     // Construction via CEGUI::String
  368.     //////////////////////////////////////////////////////////////////////////
  369.     /*!
  370.     \brief
  371.         Copy constructor - Creates a new string with the same value as \a str
  372.  
  373.     \param str
  374.         String object used to initialise the newly created string
  375.  
  376.     \return
  377.         Nothing
  378.     */
  379.     String(const String& str)
  380.     {
  381.         init();
  382.         assign(str);
  383.     }
  384.     
  385.  
  386.     /*!
  387.     \brief
  388.         Constructs a new string initialised with code points from another String object.
  389.  
  390.     \param str
  391.         String object used to initialise the newly created string
  392.  
  393.     \param str_idx
  394.         Starting code-point of \a str to be used when initialising the new String
  395.  
  396.     \param str_num
  397.         Maximum number of code points from \a str that are to be assigned to the new String
  398.  
  399.     \return
  400.         Nothing
  401.     */
  402.     String(const String& str, size_type str_idx, size_type str_num = npos)
  403.     {
  404.         init();
  405.         assign(str, str_idx, str_num);
  406.     }
  407.  
  408.     //////////////////////////////////////////////////////////////////////////
  409.     // Construction via std::string
  410.     //////////////////////////////////////////////////////////////////////////
  411.     /*!
  412.     \brief
  413.         Constructs a new string and initialises it using the std::string std_str
  414.  
  415.     \param std_str
  416.         The std::string object that is to be used to initialise the new String object.
  417.  
  418.     \note
  419.         The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
  420.         the provided data will occur.
  421.  
  422.     \return
  423.         Nothing
  424.  
  425.     \exception std::length_error    Thrown if resulting String object would be too big.
  426.     */
  427.     String(const std::string& std_str)
  428.     {
  429.         init();
  430.         assign(std_str);
  431.     }
  432.         
  433.     /*!
  434.     \brief
  435.         Constructs a new string initialised with characters from the given std::string object.
  436.  
  437.     \param std_str
  438.         std::string object used to initialise the newly created string
  439.  
  440.     \param str_idx
  441.         Starting character of \a std_str to be used when initialising the new String
  442.  
  443.     \note
  444.         The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
  445.         the provided data will occur.
  446.  
  447.     \param str_num
  448.         Maximum number of characters from \a std_str that are to be assigned to the new String
  449.  
  450.     \return
  451.         Nothing
  452.  
  453.     \exception std::length_error    Thrown if resulting String object would be too big.
  454.     */
  455.     String(const std::string& std_str, size_type str_idx, size_type str_num = npos)
  456.     {
  457.         init();
  458.         assign(std_str, str_idx, str_num);
  459.     }
  460.  
  461.  
  462.     //////////////////////////////////////////////////////////////////////////
  463.     // Construction via UTF-8 stream (for straight ASCII use, only codes 0x00 - 0x7f are valid)
  464.     //////////////////////////////////////////////////////////////////////////
  465.     /*!
  466.     \brief
  467.         Constructs a new String object and initialise it using the provided utf8 encoded string buffer.
  468.  
  469.     \param utf8_str
  470.         Pointer to a buffer containing a null-terminated Unicode string encoded as utf8 data.
  471.  
  472.     \note
  473.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  474.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  475.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  476.         results.
  477.  
  478.     \return
  479.         Nothing
  480.  
  481.     \exception std::length_error    Thrown if resulting String object would be too big.
  482.     */
  483.     String(const utf8* utf8_str)
  484.     {
  485.         init();
  486.         assign(utf8_str);
  487.     }
  488.  
  489.     /*!
  490.     \brief
  491.         Constructs a new String object and initialise it using the provided utf8 encoded string buffer.
  492.  
  493.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  494.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  495.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  496.         results.
  497.  
  498.     \param utf8_str
  499.         Pointer to a buffer containing Unicode string data encoded as utf8.
  500.  
  501.     \note
  502.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  503.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  504.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  505.         results.
  506.  
  507.     \param chars_len
  508.         Length of the provided utf8 string in code units (not code-points).
  509.  
  510.     \return
  511.         Nothing
  512.  
  513.     \exception std::length_error    Thrown if resulting String object would be too big.
  514.     */
  515.     String(const utf8* utf8_str, size_type chars_len)
  516.     {
  517.         init();
  518.         assign(utf8_str, chars_len);
  519.     }
  520.  
  521.     //////////////////////////////////////////////////////////////////////////
  522.     // Construction via code-point (using a UTF-32 code unit)
  523.     //////////////////////////////////////////////////////////////////////////
  524.     /*!
  525.     \brief
  526.         Constructs a new String that is initialised with the specified code point
  527.  
  528.     \param num
  529.         The number of times \a code_point is to be put into new String object
  530.  
  531.     \param code_point
  532.         The Unicode code point to be used when initialising the String object
  533.  
  534.     \return
  535.         Nothing
  536.  
  537.     \exception std::length_error    Thrown if resulting String object would be too big.
  538.     */
  539.     String(size_type num, utf32 code_point)
  540.     {
  541.         init();
  542.         assign(num, code_point);
  543.     }
  544.  
  545.     //////////////////////////////////////////////////////////////////////////
  546.     // Construction via iterator
  547.     //////////////////////////////////////////////////////////////////////////
  548.     // Create string with characters in the range [beg, end)
  549.     /*!
  550.     \brief
  551.         Construct a new string object and initialise it with code-points from the range [beg, end).
  552.  
  553.     \param beg
  554.         Iterator describing the start of the data to be used when initialising the String object
  555.  
  556.     \param end
  557.         Iterator describing the (exclusive) end of the data to be used when initialising the String object
  558.  
  559.     \return 
  560.         Nothing
  561.     */
  562.     String(const_iterator iter_beg, const_iterator iter_end)
  563.     {
  564.         init();
  565.         append(iter_beg, iter_end);
  566.     }
  567.  
  568.  
  569.     //////////////////////////////////////////////////////////////////////////
  570.     // Construction via c-string
  571.     //////////////////////////////////////////////////////////////////////////
  572.     /*!
  573.     \brief
  574.         Constructs a new String object and initialise it using the provided c-string.
  575.  
  576.     \param c_str
  577.         Pointer to a c-string.
  578.  
  579.     \return
  580.         Nothing
  581.  
  582.     \exception std::length_error    Thrown if resulting String object would be too big.
  583.     */
  584.     String(const char* cstr)
  585.     {
  586.         init();
  587.         assign(cstr);
  588.     }
  589.  
  590.     /*!
  591.     \brief
  592.         Constructs a new String object and initialise it using characters from the provided char array.
  593.  
  594.     \param chars
  595.         char array.
  596.  
  597.     \param chars_len
  598.         Number of chars from the array to be used.
  599.  
  600.     \return
  601.         Nothing
  602.  
  603.     \exception std::length_error    Thrown if resulting String object would be too big.
  604.     */
  605.     String(const char* chars, size_type chars_len)
  606.     {
  607.         init();
  608.         assign(chars, chars_len);
  609.     }
  610.  
  611.  
  612.     //////////////////////////////////////////////////////////////////////////
  613.     // Size operations
  614.     //////////////////////////////////////////////////////////////////////////
  615.     /*!
  616.     \brief
  617.         Returns the size of the String in code points
  618.  
  619.     \return
  620.         Number of code points currently in the String
  621.     */
  622.     size_type    size(void) const
  623.     {
  624.         return d_cplength;
  625.     }
  626.  
  627.     /*!
  628.     \brief
  629.         Returns the size of the String in code points
  630.  
  631.     \return
  632.         Number of code points currently in the String
  633.     */
  634.     size_type    length(void) const
  635.     {
  636.         return d_cplength;
  637.     }
  638.  
  639.     /*!
  640.     \brief
  641.         Returns true if the String is empty
  642.  
  643.     \return
  644.         true if the String is empty, else false.
  645.     */
  646.     bool    empty(void) const
  647.     {
  648.         return    (d_cplength == 0);
  649.     }
  650.  
  651.     /*!
  652.     \brief
  653.         Returns the maximum size of a String.
  654.  
  655.         Any operation that would result in a String that is larger than this value will throw the std::length_error exception.
  656.  
  657.     \return
  658.         The maximum number of code points that a string can contain
  659.     */
  660.     static size_type    max_size(void)
  661.     {
  662.         return (((size_type)-1) / sizeof(utf32));
  663.     }
  664.  
  665.     //////////////////////////////////////////////////////////////////////////
  666.     // Capacity Operations
  667.     //////////////////////////////////////////////////////////////////////////
  668.     // return the number of code points the string could hold without re-allocation
  669.     // (due to internal encoding this will always report the figure for worst-case encoding, and could even be < size()!)
  670.     /*!
  671.     \brief
  672.         Return the number of code points that the String could hold before a re-allocation would be required.
  673.  
  674.     \return
  675.         Size of the current reserve buffer.  This is the maximum number of code points the String could hold before a buffer
  676.         re-allocation would be required
  677.     */
  678.     size_type capacity(void) const
  679.     {
  680.         return d_reserve - 1;
  681.     }
  682.  
  683.     // reserve internal memory for at-least 'num' code-points (characters).  if num is 0, request is shrink-to-fit.
  684.     /*!
  685.     \brief
  686.         Specifies the amount of reserve capacity to allocate.
  687.  
  688.     \param num
  689.         The number of code points to allocate space for.  If \a num is larger that the current reserve, then a re-allocation will occur.  If
  690.         \a num is smaller than the current reserve (but not 0) the buffer may be shrunk to the larger of the specified number, or the current
  691.         String size (operation is currently not implemented).  If \a num is 0, then the buffer is re-allocated to fit the current String size.
  692.  
  693.     \return
  694.         Nothing
  695.  
  696.     \exception std::length_error    Thrown if resulting String object would be too big.
  697.     */
  698.     void    reserve(size_type num = 0)
  699.     {
  700.         if (num == 0)
  701.             trim();
  702.         else
  703.             grow(num);
  704.     }
  705.  
  706.     //////////////////////////////////////////////////////////////////////////
  707.     // Comparisons
  708.     //////////////////////////////////////////////////////////////////////////
  709.     /*!
  710.     \brief
  711.         Compares this String with the String 'str'.
  712.  
  713.     \note
  714.         This does currently not properly consider Unicode and / or the system locale.
  715.  
  716.     \param str
  717.         The String object that is to compared with this String.
  718.  
  719.     \return
  720.         -  0 if the String objects are equal
  721.         - <0 if this String is lexicographically smaller than \a str
  722.         - >0 if this String is lexicographically greater than \a str
  723.     */
  724.     int        compare(const String& str) const
  725.     {
  726.         return compare(0, d_cplength, str);
  727.     }
  728.  
  729.     /*!
  730.     \brief
  731.         Compares code points from this String with code points from the String 'str'.
  732.  
  733.     \note
  734.         This does currently not properly consider Unicode and / or the system locale.
  735.  
  736.     \param idx
  737.         Index of the first code point from this String to consider.
  738.  
  739.     \param len
  740.         Maximum number of code points from this String to consider.
  741.  
  742.     \param str
  743.         The String object that is to compared with this String.
  744.  
  745.     \param str_idx
  746.         Index of the first code point from String \a str to consider.
  747.  
  748.     \param str_len
  749.         Maximum number of code points from String \a str to consider
  750.  
  751.     \return
  752.         -  0 if the specified sub-strings are equal
  753.         - <0 if specified sub-strings are lexicographically smaller than \a str
  754.         - >0 if specified sub-strings are lexicographically greater than \a str
  755.  
  756.     \exception std::out_of_range    Thrown if either \a idx or \a str_idx are invalid.
  757.     */
  758.     int        compare(size_type idx, size_type len, const String& str, size_type str_idx = 0, size_type str_len = npos) const
  759.     {
  760.         if ((d_cplength < idx) || (str.d_cplength < str_idx))
  761.             throw std::out_of_range("Index is out of range for CEGUI::String");
  762.  
  763.         if ((len == npos) || (idx + len > d_cplength))
  764.             len = d_cplength - idx;
  765.  
  766.         if ((str_len == npos) || (str_idx + str_len > str.d_cplength))
  767.             str_len = str.d_cplength - str_idx;
  768.  
  769.         int val = (len == 0) ? 0 : utf32_comp_utf32(&ptr()[idx], &str.ptr()[str_idx], (len < str_len) ? len : str_len);
  770.  
  771.         return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
  772.     }
  773.  
  774.  
  775.     /*!
  776.     \brief
  777.         Compares this String with the std::string 'std_str'.
  778.  
  779.     \note
  780.         This does currently not properly consider Unicode and / or the system locale.
  781.  
  782.     \param std_str
  783.         The std::string object that is to compared with this String.
  784.  
  785.     \note
  786.         Characters from \a std_str are considered to represent Unicode code points in the range 0x00..0xFF.  No translation of
  787.         the encountered data is performed.
  788.  
  789.     \return
  790.         -  0 if the string objects are equal
  791.         - <0 if this string is lexicographically smaller than \a std_str
  792.         - >0 if this string is lexicographically greater than \a std_str
  793.     */
  794.     int        compare(const std::string& std_str) const
  795.     {
  796.         return compare(0, d_cplength, std_str);
  797.     }
  798.  
  799.  
  800.     /*!
  801.     \brief
  802.         Compares code points from this String with code points from the std::string 'std_str'.
  803.  
  804.     \note
  805.         This does currently not properly consider Unicode and / or the system locale.
  806.  
  807.     \param idx
  808.         Index of the first code point from this String to consider.
  809.  
  810.     \param len
  811.         Maximum number of code points from this String to consider.
  812.  
  813.     \param std_str
  814.         The std::string object that is to compared with this String.
  815.  
  816.     \note
  817.         Characters from \a std_str are considered to represent Unicode code points in the range 0x00..0xFF.  No translation of
  818.         the encountered data is performed.
  819.  
  820.     \param str_idx
  821.         Index of the first character from std::string \a std_str to consider.
  822.  
  823.     \param str_len
  824.         Maximum number of characters from std::string \a std_str to consider
  825.  
  826.     \return
  827.         -  0 if the specified sub-strings are equal
  828.         - <0 if specified sub-strings are lexicographically smaller than \a std_str
  829.         - >0 if specified sub-strings are lexicographically greater than \a std_str
  830.  
  831.     \exception std::out_of_range    Thrown if either \a idx or \a str_idx are invalid.
  832.     */
  833.     int        compare(size_type idx, size_type len, const std::string& std_str, size_type str_idx = 0, size_type str_len = npos) const
  834.     {
  835.         if (d_cplength < idx)
  836.             throw std::out_of_range("Index is out of range for CEGUI::String");
  837.  
  838.         if (std_str.size() < str_idx)
  839.             throw std::out_of_range("Index is out of range for std::string");
  840.  
  841.         if ((len == npos) || (idx + len > d_cplength))
  842.             len = d_cplength - idx;
  843.  
  844.         if ((str_len == npos) || (str_idx + str_len > std_str.size()))
  845.             str_len = (size_type)std_str.size() - str_idx;
  846.  
  847.         int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], &std_str.c_str()[str_idx], (len < str_len) ? len : str_len);
  848.  
  849.         return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_len) ? -1 : (len == str_len) ? 0 : 1;
  850.     }
  851.  
  852.  
  853.     /*!
  854.     \brief
  855.         Compares this String with the null-terminated utf8 encoded 'utf8_str'.
  856.  
  857.     \note
  858.         This does currently not properly consider Unicode and / or the system locale.
  859.  
  860.     \param utf8_str
  861.         The buffer containing valid Unicode data encoded as utf8 that is to compared with this String.
  862.  
  863.     \note
  864.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  865.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  866.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  867.         results.
  868.  
  869.     \return
  870.         -  0 if the strings are equal
  871.         - <0 if this string is lexicographically smaller than \a utf8_str
  872.         - >0 if this string is lexicographically greater than \a utf8_str
  873.     */
  874.     int        compare(const utf8* utf8_str) const
  875.     {
  876.         return compare(0, d_cplength, utf8_str, encoded_size(utf8_str));
  877.     }
  878.  
  879.  
  880.     /*!
  881.     \brief
  882.         Compares code points from this String with the null-terminated utf8 encoded 'utf8_str'.
  883.  
  884.     \note
  885.         This does currently not properly consider Unicode and / or the system locale.
  886.  
  887.     \param idx
  888.         Index of the first code point from this String to consider.
  889.  
  890.     \param len
  891.         Maximum number of code points from this String to consider.
  892.  
  893.     \param utf8_str
  894.         The buffer containing valid Unicode data encoded as utf8 that is to compared with this String.
  895.  
  896.     \note
  897.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  898.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  899.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  900.         results.
  901.  
  902.     \return
  903.         -  0 if the specified sub-strings are equal
  904.         - <0 if specified sub-strings are lexicographically smaller than \a utf8_str
  905.         - >0 if specified sub-strings are lexicographically greater than \a utf8_str
  906.  
  907.     \exception std::out_of_range    Thrown if \a idx is invalid.
  908.     */
  909.     int        compare(size_type idx, size_type len, const utf8* utf8_str) const
  910.     {
  911.         return compare(idx, len, utf8_str, encoded_size(utf8_str));
  912.     }
  913.  
  914.     /*!
  915.     \brief
  916.         Compares code points from this String with the utf8 encoded data in buffer 'utf8_str'.
  917.  
  918.     \note
  919.         This does currently not properly consider Unicode and / or the system locale.
  920.  
  921.     \param idx
  922.         Index of the first code point from this String to consider.
  923.  
  924.     \param len
  925.         Maximum number of code points from this String to consider.
  926.  
  927.     \param utf8_str
  928.         The buffer containing valid Unicode data encoded as utf8 that is to compared with this String.
  929.  
  930.     \note
  931.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  932.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  933.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  934.         results.
  935.  
  936.     \param str_cplen
  937.         The number of encoded code points in the buffer \a utf8_str (this is not the same as the number of code units).
  938.  
  939.     \return
  940.         -  0 if the specified sub-strings are equal
  941.         - <0 if specified sub-strings are lexicographically smaller than \a utf8_str
  942.         - >0 if specified sub-strings are lexicographically greater than \a utf8_str
  943.  
  944.     \exception std::out_of_range    Thrown if \a idx is invalid.
  945.     \exception std::length_error    Thrown if \a str_cplen is set to npos.
  946.     */
  947.     int        compare(size_type idx, size_type len, const utf8* utf8_str, size_type str_cplen) const
  948.     {
  949.         if (d_cplength < idx)
  950.             throw std::out_of_range("Index is out of range for CEGUI::String");
  951.  
  952.         if (str_cplen == npos)
  953.             throw std::length_error("Length for utf8 encoded string can not be 'npos'");
  954.  
  955.         if ((len == npos) || (idx + len > d_cplength))
  956.             len = d_cplength - idx;
  957.  
  958.         int val = (len == 0) ? 0 : utf32_comp_utf8(&ptr()[idx], utf8_str, (len < str_cplen) ? len : str_cplen);
  959.  
  960.         return (val != 0) ? ((val < 0) ? -1 : 1) : (len < str_cplen) ? -1 : (len == str_cplen) ? 0 : 1;
  961.     }
  962.  
  963.  
  964.     /*!
  965.     \brief
  966.         Compares this String with the given c-string.
  967.  
  968.     \note
  969.         This does currently not properly consider Unicode and / or the system locale.
  970.  
  971.     \param c_str
  972.         The c-string that is to compared with this String.
  973.  
  974.     \return
  975.         -  0 if the strings are equal
  976.         - <0 if this string is lexicographically smaller than \a c_str
  977.         - >0 if this string is lexicographically greater than \a c_str
  978.     */
  979.     int        compare(const char* cstr) const
  980.     {
  981.         return compare(0, d_cplength, cstr, strlen(cstr));
  982.     }
  983.  
  984.  
  985.     /*!
  986.     \brief
  987.         Compares code points from this String with the given c-string.
  988.  
  989.     \note
  990.         This does currently not properly consider Unicode and / or the system locale.
  991.  
  992.     \param idx
  993.         Index of the first code point from this String to consider.
  994.  
  995.     \param len
  996.         Maximum number of code points from this String to consider.
  997.  
  998.     \param c_str
  999.         The c-string that is to compared with this String.
  1000.  
  1001.     \return
  1002.         -  0 if the specified sub-strings are equal
  1003.         - <0 if specified sub-strings are lexicographically smaller than \a c_str
  1004.         - >0 if specified sub-strings are lexicographically greater than \a c_str
  1005.  
  1006.     \exception std::out_of_range    Thrown if \a idx is invalid.
  1007.     */
  1008.     int        compare(size_type idx, size_type len, const char* cstr) const
  1009.     {
  1010.         return compare(idx, len, cstr, strlen(cstr));
  1011.     }
  1012.  
  1013.  
  1014.     /*!
  1015.     \brief
  1016.         Compares code points from this String with chars in the given char array.
  1017.  
  1018.     \note
  1019.         This does currently not properly consider Unicode and / or the system locale.
  1020.  
  1021.     \param idx
  1022.         Index of the first code point from this String to consider.
  1023.  
  1024.     \param len
  1025.         Maximum number of code points from this String to consider.
  1026.  
  1027.     \param chars
  1028.         The array containing the chars that are to compared with this String.
  1029.  
  1030.     \param chars_len
  1031.         The number of chars in the array.
  1032.  
  1033.     \return
  1034.         -  0 if the specified sub-strings are equal
  1035.         - <0 if specified sub-strings are lexicographically smaller than \a chars
  1036.         - >0 if specified sub-strings are lexicographically greater than \a chars
  1037.  
  1038.     \exception std::out_of_range    Thrown if \a idx is invalid.
  1039.     \exception std::length_error    Thrown if \a chars_len is set to npos.
  1040.     */
  1041.     int        compare(size_type idx, size_type len, const char* chars, size_type chars_len) const
  1042.     {
  1043.         if (d_cplength < idx)
  1044.             throw std::out_of_range("Index is out of range for CEGUI::String");
  1045.  
  1046.         if (chars_len == npos)
  1047.             throw std::length_error("Length for char array can not be 'npos'");
  1048.  
  1049.         if ((len == npos) || (idx + len > d_cplength))
  1050.             len = d_cplength - idx;
  1051.  
  1052.         int val = (len == 0) ? 0 : utf32_comp_char(&ptr()[idx], chars, (len < chars_len) ? len : chars_len);
  1053.  
  1054.         return (val != 0) ? ((val < 0) ? -1 : 1) : (len < chars_len) ? -1 : (len == chars_len) ? 0 : 1;
  1055.     }
  1056.  
  1057.  
  1058.     //////////////////////////////////////////////////////////////////////////
  1059.     // Character access
  1060.     //////////////////////////////////////////////////////////////////////////
  1061.     /*!
  1062.     \brief
  1063.         Returns the code point at the given index.
  1064.  
  1065.     \param idx
  1066.         Zero based index of the code point to be returned.
  1067.  
  1068.     \note
  1069.         - For constant strings length()/size() provide a valid index and will access the default utf32 value.
  1070.         - For non-constant strings length()/size() is an invalid index, and acceesing (especially writing) this index could cause string corruption.
  1071.  
  1072.     \return
  1073.         The utf32 code point at the given index within the String.
  1074.     */
  1075.     reference    operator[](size_type idx)
  1076.     {
  1077.         return (ptr()[idx]);
  1078.     }
  1079.  
  1080.     /*!
  1081.     \brief
  1082.         Returns the code point at the given index.
  1083.  
  1084.     \param idx
  1085.         Zero based index of the code point to be returned.
  1086.  
  1087.     \note
  1088.         - For constant strings length()/size() provide a valid index and will access the default utf32 value.
  1089.         - For non-constant strings length()/size() is an invalid index, and acceesing (especially writing) this index could cause string corruption.
  1090.  
  1091.     \return
  1092.         The utf32 code point at the given index within the String.
  1093.     */
  1094.     value_type    operator[](size_type idx) const
  1095.     {
  1096.         return ptr()[idx];
  1097.     }
  1098.  
  1099.     /*!
  1100.     \brief
  1101.         Returns the code point at the given index.
  1102.  
  1103.     \param idx
  1104.         Zero based index of the code point to be returned.
  1105.  
  1106.     \return
  1107.         The utf32 code point at the given index within the String.
  1108.  
  1109.     \exception std::out_of_range    Thrown if \a idx is >= length().
  1110.     */
  1111.     reference    at(size_type idx)
  1112.     {
  1113.         if (d_cplength <= idx)
  1114.             throw std::out_of_range("Index is out of range for CEGUI::String");
  1115.  
  1116.         return ptr()[idx];
  1117.     }
  1118.  
  1119.     /*!
  1120.     \brief
  1121.         Returns the code point at the given index.
  1122.  
  1123.     \param idx
  1124.         Zero based index of the code point to be returned.
  1125.  
  1126.     \return
  1127.         The utf32 code point at the given index within the String.
  1128.  
  1129.     \exception std::out_of_range    Thrown if \a idx is >= length().
  1130.     */
  1131.     const_reference    at(size_type idx) const
  1132.     {
  1133.         if (d_cplength <= idx)
  1134.             throw std::out_of_range("Index is out of range for CEGUI::String");
  1135.  
  1136.         return ptr()[idx];
  1137.     }
  1138.  
  1139.  
  1140.     //////////////////////////////////////////////////////////////////////////
  1141.     // C-Strings and arrays
  1142.     //////////////////////////////////////////////////////////////////////////
  1143.     /*!
  1144.     \brief
  1145.         Returns contents of the String as a null terminated string of utf8 encoded data.
  1146.  
  1147.     \return
  1148.         Pointer to a char buffer containing the contents of the String encoded as null-terminated utf8 data.
  1149.  
  1150.     \note
  1151.         The buffer returned from this function is owned by the String object.
  1152.  
  1153.     \note
  1154.         Any function that modifies the String data will invalidate the buffer returned by this call.
  1155.     */
  1156.     const char* c_str(void) const
  1157.     {
  1158.         return (const char*)build_utf8_buff();
  1159.     }
  1160.  
  1161.     /*!
  1162.     \brief
  1163.         Returns contents of the String as utf8 encoded data.
  1164.  
  1165.     \return
  1166.         Pointer to a buffer containing the contents of the String encoded utf8 data.
  1167.  
  1168.     \note
  1169.         The buffer returned from this function is owned by the String object.
  1170.  
  1171.     \note
  1172.         Any function that modifies the String data will invalidate the buffer returned by this call.
  1173.     */
  1174.     const utf8* data(void) const
  1175.     {
  1176.         return build_utf8_buff();
  1177.     }
  1178.  
  1179.     // copy, at most, 'len' code-points of the string, begining with code-point 'idx', into the array 'buf' as valid utf8 encoded data
  1180.     // return number of utf8 code units placed into the buffer
  1181.     /*!
  1182.     \brief
  1183.         Copies an area of the String into the provided buffer as encoded utf8 data.
  1184.  
  1185.     \param buf
  1186.         Pointer to a buffer that is to receive the encoded data (this must be big enough to hold the encoded data)
  1187.  
  1188.     \param len
  1189.         Maximum number of code points from the String that should be encoded into the buffer
  1190.     
  1191.     \param idx
  1192.         Index of the first code point to be encoded into the buffer
  1193.  
  1194.     \return
  1195.         The number of utf8 encoded code units transferred to the buffer.
  1196.  
  1197.         \note A code unit does not equal a code point.  A utf32 code point, when encoded as utf8, can occupy between 1 and 4 code units.
  1198.  
  1199.     \exception std::out_of_range    Thrown if \a idx was invalid for this String.
  1200.     */
  1201.     size_type    copy(utf8* buf, size_type len = npos, size_type idx = 0) const
  1202.     {
  1203.         if (d_cplength < idx)
  1204.             throw std::out_of_range("Index is out of range for CEGUI::String");
  1205.  
  1206.         if (len == npos)
  1207.             len = d_cplength;
  1208.  
  1209.         return encode(&ptr()[idx], buf, npos, len);
  1210.     }
  1211.  
  1212.     //////////////////////////////////////////////////////////////////////////
  1213.     // UTF8 Encoding length information
  1214.     //////////////////////////////////////////////////////////////////////////
  1215.     // return the number of bytes required to hold 'num' code-points, starting at code-point 'idx', of the the string when encoded as utf8 data.
  1216.     /*!
  1217.     \brief
  1218.         Return the number of utf8 code units required to hold an area of the String when encoded as utf8 data
  1219.  
  1220.     \param num
  1221.         Maximum number of code points to consider when calculating utf8 encoded size.
  1222.  
  1223.     \param idx
  1224.         Index of the first code point to consider when calculating the utf8 encoded size
  1225.  
  1226.     \return
  1227.         The number of utf8 code units (bytes) required to hold the specified sub-string when encoded as utf8 data.
  1228.  
  1229.     \exception std::out_of_range    Thrown if \a idx was invalid for this String.
  1230.     */
  1231.     size_type    utf8_stream_len(size_type num = npos, size_type idx = 0)
  1232.     {
  1233.         using namespace std;
  1234.  
  1235.         if (d_cplength < idx)
  1236.             throw out_of_range("Index was out of range for CEGUI::String object");
  1237.  
  1238.         size_type    maxlen = d_cplength - idx;
  1239.  
  1240.         return encoded_size(&ptr()[idx], ceguimin(num, maxlen));
  1241.     }
  1242.  
  1243.     //////////////////////////////////////////////////////////////////////////
  1244.     // Assignment Functions
  1245.     //////////////////////////////////////////////////////////////////////////
  1246.     /*!
  1247.     \brief
  1248.         Assign the value of String \a str to this String
  1249.  
  1250.     \param str
  1251.         String object containing the string value to be assigned.
  1252.  
  1253.     \return
  1254.         This String after the assignment has happened
  1255.     */
  1256.     String&    operator=(const String& str)
  1257.     {
  1258.         return assign(str);
  1259.     }
  1260.  
  1261.     /*!
  1262.     \brief
  1263.         Assign a sub-string of String \a str to this String
  1264.  
  1265.     \param str
  1266.         String object containing the string data to be assigned.
  1267.  
  1268.     \param str_idx
  1269.         Index of the first code point in \a str that is to be assigned
  1270.  
  1271.     \param str_num
  1272.         Maximum number of code points from \a str that are be be assigned
  1273.  
  1274.     \return
  1275.         This String after the assignment has happened
  1276.  
  1277.     \exception std::out_of_range    Thrown if str_idx is invalid for \a str
  1278.     */
  1279.     String&    assign(const String& str, size_type str_idx = 0, size_type str_num = npos)
  1280.     {
  1281.         if (str.d_cplength < str_idx)
  1282.             throw std::out_of_range("Index was out of range for CEGUI::String object");
  1283.  
  1284.         if (str_num == npos)
  1285.             str_num = str.d_cplength - str_idx;
  1286.  
  1287.         grow(str_num);
  1288.         setlen(str_num);
  1289.         memcpy(ptr(), &str.ptr()[str_idx], str_num * sizeof(utf32));
  1290.         
  1291.         return *this;
  1292.     }
  1293.  
  1294.     /*!
  1295.     \brief
  1296.         Assign the value of std::string \a std_str to this String
  1297.  
  1298.     \note
  1299.         The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
  1300.         the provided data will occur.
  1301.  
  1302.     \param std_str
  1303.         std::string object containing the string value to be assigned.
  1304.  
  1305.     \return
  1306.         This String after the assignment has happened
  1307.  
  1308.     \exception std::length_error    Thrown if the resulting String would have been too large.
  1309.     */
  1310.     String&    operator=(const std::string& std_str)
  1311.     {
  1312.         return assign(std_str);
  1313.     }
  1314.  
  1315.     /*!
  1316.     \brief
  1317.         Assign a sub-string of std::string \a std_str to this String
  1318.  
  1319.     \note
  1320.         The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
  1321.         the provided data will occur.
  1322.  
  1323.     \param std_str
  1324.         std::string object containing the string value to be assigned.
  1325.  
  1326.     \param str_idx
  1327.         Index of the first character of \a std_str to be assigned
  1328.  
  1329.     \param str_num
  1330.         Maximum number of characters from \a std_str to be assigned
  1331.  
  1332.     \return
  1333.         This String after the assignment has happened
  1334.  
  1335.     \exception std::out_of_range    Thrown if \a str_idx is invalid for \a std_str
  1336.     \exception std::length_error    Thrown if the resulting String would have been too large.
  1337.     */
  1338.     String&    assign(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
  1339.     {
  1340.         if (std_str.size() < str_idx)
  1341.             throw std::out_of_range("Index was out of range for std::string object");
  1342.  
  1343.         if (str_num == npos)
  1344.             str_num = (size_type)std_str.size() - str_idx;
  1345.  
  1346.         grow(str_num);
  1347.         setlen(str_num);
  1348.  
  1349.         while(str_num--)
  1350.         {
  1351.             ((*this)[str_num]) = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num + str_idx]));
  1352.         }
  1353.  
  1354.         return *this;
  1355.     }
  1356.  
  1357.     /*!
  1358.     \brief
  1359.         Assign to this String the string value represented by the given null-terminated utf8 encoded data
  1360.  
  1361.     \note
  1362.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  1363.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  1364.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  1365.         results.
  1366.  
  1367.     \param utf8_str
  1368.         Buffer containing valid null-terminated utf8 encoded data
  1369.  
  1370.     \return
  1371.         This String after the assignment has happened
  1372.  
  1373.     \exception std::length_error    Thrown if the resulting String would have been too large.
  1374.     */
  1375.     String&    operator=(const utf8* utf8_str)
  1376.     {
  1377.         return assign(utf8_str, utf_length(utf8_str));
  1378.     }
  1379.  
  1380.     /*!
  1381.     \brief
  1382.         Assign to this String the string value represented by the given null-terminated utf8 encoded data
  1383.  
  1384.     \note
  1385.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  1386.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  1387.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  1388.         results.
  1389.  
  1390.     \param utf8_str
  1391.         Buffer containing valid null-terminated utf8 encoded data
  1392.  
  1393.     \return
  1394.         This String after the assignment has happened
  1395.  
  1396.     \exception std::length_error    Thrown if the resulting String would have been too large.
  1397.     */
  1398.     String&    assign(const utf8* utf8_str)
  1399.     {
  1400.         return assign(utf8_str, utf_length(utf8_str));
  1401.     }
  1402.  
  1403.     /*!
  1404.     \brief
  1405.         Assign to this String the string value represented by the given utf8 encoded data
  1406.  
  1407.     \note
  1408.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  1409.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  1410.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  1411.         results.
  1412.  
  1413.     \param utf8_str
  1414.         Buffer containing valid utf8 encoded data
  1415.  
  1416.     \param str_num
  1417.         Number of code units (not code points) in the buffer pointed to by \a utf8_str
  1418.  
  1419.     \return
  1420.         This String after the assignment has happened
  1421.  
  1422.     \exception std::length_error    Thrown if the resulting String would have been too large, or if str_num is 'npos'.
  1423.     */
  1424.     String&    assign(const utf8* utf8_str, size_type str_num)
  1425.     {
  1426.         if (str_num == npos)
  1427.             throw std::length_error("Length for utf8 encoded string can not be 'npos'");
  1428.  
  1429.         size_type enc_sze = encoded_size(utf8_str, str_num);
  1430.  
  1431.         grow(enc_sze);
  1432.         encode(utf8_str, ptr(), d_reserve, str_num);
  1433.         setlen(enc_sze);
  1434.         return *this;
  1435.     }
  1436.  
  1437.     /*!
  1438.     \brief
  1439.         Assigns the specified utf32 code point to this String.  Result is always a String 1 code point in length.
  1440.  
  1441.     \param code_point
  1442.         Valid utf32 Unicode code point to be assigned to the string
  1443.  
  1444.     \return
  1445.         This String after assignment
  1446.     */
  1447.     String&    operator=(utf32 code_point)
  1448.     {
  1449.         return assign(1, code_point);
  1450.     }
  1451.  
  1452.     /*!
  1453.     \brief
  1454.         Assigns the specified code point repeatedly to the String
  1455.  
  1456.     \param num
  1457.         The number of times to assign the code point
  1458.  
  1459.     \param code_point
  1460.         Valid utf32 Unicode code point to be assigned to the string
  1461.  
  1462.     \return
  1463.         This String after assignment.
  1464.  
  1465.     \exception std::length_error    Thrown if \a num was 'npos'
  1466.     */
  1467.     String&    assign(size_type num, utf32 code_point)
  1468.     {
  1469.         if (num == npos)
  1470.             throw std::length_error("Code point count can not be 'npos'");
  1471.  
  1472.         grow(num);
  1473.         setlen(num);
  1474.         utf32* p = ptr();
  1475.  
  1476.         while(num--)
  1477.             *p++ = code_point;
  1478.  
  1479.         return *this;
  1480.     }
  1481.  
  1482.  
  1483.     /*!
  1484.     \brief
  1485.         Assign to this String the given C-string.
  1486.  
  1487.     \param c_str
  1488.         Pointer to a valid C style string.
  1489.  
  1490.     \return
  1491.         This String after the assignment has happened
  1492.  
  1493.     \exception std::length_error    Thrown if the resulting String would have been too large.
  1494.     */
  1495.     String&    operator=(const char* cstr)
  1496.     {
  1497.         return assign(cstr, strlen(cstr));
  1498.     }
  1499.  
  1500.  
  1501.     /*!
  1502.     \brief
  1503.         Assign to this String the given C-string.
  1504.  
  1505.     \param c_str
  1506.         Pointer to a valid C style string.
  1507.  
  1508.     \return
  1509.         This String after the assignment has happened
  1510.  
  1511.     \exception std::length_error    Thrown if the resulting String would have been too large.
  1512.     */
  1513.     String&    assign(const char* cstr)
  1514.     {
  1515.         return assign(cstr, strlen(cstr));
  1516.     }
  1517.  
  1518.  
  1519.     /*!
  1520.     \brief
  1521.         Assign to this String a number of chars from a char array.
  1522.  
  1523.     \param chars
  1524.         char array.
  1525.  
  1526.     \param chars_len
  1527.         Number of chars to be assigned.
  1528.  
  1529.     \return
  1530.         This String after the assignment has happened
  1531.  
  1532.     \exception std::length_error    Thrown if the resulting String would have been too large.
  1533.     */
  1534.     String&    assign(const char* chars, size_type chars_len)
  1535.     {
  1536.         grow(chars_len);
  1537.         utf32* pt = ptr();
  1538.  
  1539.         for (size_type i = 0; i < chars_len; ++i)
  1540.         {
  1541.             *pt++ = static_cast<utf32>(static_cast<unsigned char>(*chars++));
  1542.         }
  1543.  
  1544.         setlen(chars_len);
  1545.         return *this;
  1546.     }
  1547.  
  1548.  
  1549.     /*!
  1550.     \brief
  1551.         Swaps the value of this String with the given String \a str
  1552.  
  1553.     \param str
  1554.         String object whos value is to be swapped with this String.
  1555.  
  1556.     \return
  1557.         Nothing
  1558.     */
  1559.     void    swap(String& str)
  1560.     {
  1561.         size_type    temp_len    = d_cplength;
  1562.         d_cplength = str.d_cplength;
  1563.         str.d_cplength = temp_len;
  1564.  
  1565.         size_type    temp_res    = d_reserve;
  1566.         d_reserve = str.d_reserve;
  1567.         str.d_reserve = temp_res;
  1568.  
  1569.         utf32*        temp_buf    = d_buffer;
  1570.         d_buffer = str.d_buffer;
  1571.         str.d_buffer = temp_buf;
  1572.  
  1573.         // see if we need to swap 'quick buffer' data
  1574.         if (temp_res <= STR_QUICKBUFF_SIZE)
  1575.         {
  1576.             utf32        temp_qbf[STR_QUICKBUFF_SIZE];
  1577.  
  1578.             memcpy(temp_qbf, d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
  1579.             memcpy(d_quickbuff, str.d_quickbuff, STR_QUICKBUFF_SIZE * sizeof(utf32));
  1580.             memcpy(str.d_quickbuff, temp_qbf, STR_QUICKBUFF_SIZE * sizeof(utf32));
  1581.         }
  1582.  
  1583.     }
  1584.  
  1585.     //////////////////////////////////////////////////////////////////////////
  1586.     // Appending Functions
  1587.     //////////////////////////////////////////////////////////////////////////
  1588.     /*!
  1589.     \brief
  1590.         Appends the String \a str
  1591.  
  1592.     \param str
  1593.         String object that is to be appended
  1594.  
  1595.     \return
  1596.         This String after the append operation
  1597.  
  1598.     \exception std::length_error    Thrown if resulting String would be too large.
  1599.     */
  1600.     String&    operator+=(const String& str)
  1601.     {
  1602.         return append(str);
  1603.     }
  1604.  
  1605.     /*!
  1606.     \brief
  1607.         Appends a sub-string of the String \a str
  1608.  
  1609.     \param str
  1610.         String object containing data to be appended
  1611.  
  1612.     \param str_idx
  1613.         Index of the first code point to be appended
  1614.  
  1615.     \param str_num
  1616.         Maximum number of code points to be appended
  1617.  
  1618.     \return
  1619.         This String after the append operation
  1620.  
  1621.     \exception std::out_of_range    Thrown if \a str_idx is invalid for \a str.
  1622.     \exception std::length_error    Thrown if resulting String would be too large.
  1623.     */
  1624.     String& append(const String& str, size_type str_idx = 0, size_type str_num = npos)
  1625.     {
  1626.         if (str.d_cplength < str_idx)
  1627.             throw std::out_of_range("Index is out of range for CEGUI::String");
  1628.  
  1629.         if (str_num == npos)
  1630.             str_num = str.d_cplength - str_idx;
  1631.  
  1632.         grow(d_cplength + str_num);
  1633.         memcpy(&ptr()[d_cplength], &str.ptr()[str_idx], str_num * sizeof(utf32));
  1634.         setlen(d_cplength + str_num);
  1635.         return *this;
  1636.     }
  1637.  
  1638.  
  1639.     /*!
  1640.     \brief
  1641.         Appends the std::string \a std_str
  1642.  
  1643.     \param std_str
  1644.         std::string object that is to be appended
  1645.  
  1646.     \note
  1647.         The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
  1648.         the provided data will occur.
  1649.  
  1650.     \return
  1651.         This String after the append operation
  1652.  
  1653.     \exception std::length_error    Thrown if resulting String would be too large.
  1654.     */
  1655.     String&    operator+=(const std::string& std_str)
  1656.     {
  1657.         return append(std_str);
  1658.     }
  1659.  
  1660.     /*!
  1661.     \brief
  1662.         Appends a sub-string of the std::string \a std_str
  1663.  
  1664.     \param std_str
  1665.         std::string object containing data to be appended
  1666.  
  1667.     \note
  1668.         The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
  1669.         the provided data will occur.
  1670.  
  1671.     \param str_idx
  1672.         Index of the first character to be appended
  1673.  
  1674.     \param str_num
  1675.         Maximum number of characters to be appended
  1676.  
  1677.     \return
  1678.         This String after the append operation
  1679.  
  1680.     \exception std::out_of_range    Thrown if \a str_idx is invalid for \a std_str.
  1681.     \exception std::length_error    Thrown if resulting String would be too large.
  1682.     */
  1683.     String& append(const std::string& std_str, size_type str_idx = 0, size_type str_num = npos)
  1684.     {
  1685.         if (std_str.size() < str_idx)
  1686.             throw std::out_of_range("Index is out of range for std::string");
  1687.  
  1688.         if (str_num == npos)
  1689.             str_num = (size_type)std_str.size() - str_idx;
  1690.  
  1691.         size_type newsze = d_cplength + str_num;
  1692.  
  1693.         grow(newsze);
  1694.         utf32* pt = &ptr()[newsze-1];
  1695.  
  1696.         while(str_num--)
  1697.             *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_num]));
  1698.  
  1699.         setlen(newsze);
  1700.         return *this;
  1701.     }
  1702.  
  1703.  
  1704.     /*!
  1705.     \brief
  1706.         Appends to the String the null-terminated utf8 encoded data in the buffer utf8_str.
  1707.  
  1708.     \param utf8_str
  1709.         buffer holding the null-terminated utf8 encoded data that is to be appended
  1710.  
  1711.     \note
  1712.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  1713.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  1714.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  1715.         results.
  1716.  
  1717.     \return
  1718.         This String after the append operation
  1719.  
  1720.     \exception std::length_error    Thrown if resulting String would be too large.
  1721.     */
  1722.     String&    operator+=(const utf8* utf8_str)
  1723.     {
  1724.         return append(utf8_str, utf_length(utf8_str));
  1725.     }
  1726.  
  1727.     /*!
  1728.     \brief
  1729.         Appends to the String the null-terminated utf8 encoded data in the buffer utf8_str.
  1730.  
  1731.     \param utf8_str
  1732.         Buffer holding the null-terminated utf8 encoded data that is to be appended
  1733.  
  1734.     \note
  1735.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  1736.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  1737.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  1738.         results.
  1739.  
  1740.     \return
  1741.         This String after the append operation
  1742.  
  1743.     \exception std::length_error    Thrown if resulting String would be too large.
  1744.     */
  1745.     String& append(const utf8* utf8_str)
  1746.     {
  1747.         return append(utf8_str, utf_length(utf8_str));
  1748.     }
  1749.  
  1750.  
  1751.     /*!
  1752.     \brief
  1753.         Appends to the String the utf8 encoded data in the buffer utf8_str.
  1754.  
  1755.     \param utf8_str
  1756.         Buffer holding the utf8 encoded data that is to be appended
  1757.  
  1758.     \note
  1759.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  1760.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  1761.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  1762.         results.
  1763.  
  1764.     \param len
  1765.         Number of code units (not code points) in the buffer to be appended
  1766.  
  1767.     \return
  1768.         This String after the append operation
  1769.  
  1770.     \exception std::length_error    Thrown if resulting String would be too large, or if \a len was 'npos'
  1771.     */
  1772.     String& append(const utf8* utf8_str, size_type len)
  1773.     {
  1774.         if (len == npos)
  1775.             throw std::length_error("Length for utf8 encoded string can not be 'npos'");
  1776.  
  1777.         size_type encsz = encoded_size(utf8_str, len);
  1778.         size_type newsz = d_cplength + encsz;
  1779.  
  1780.         grow(newsz);
  1781.         encode(utf8_str, &ptr()[d_cplength], encsz, len);
  1782.         setlen(newsz);
  1783.  
  1784.         return *this;
  1785.     }
  1786.  
  1787.  
  1788.     /*!
  1789.     \brief
  1790.         Appends a single code point to the string
  1791.  
  1792.     \param code_point
  1793.         utf32 Unicode code point that is to be appended
  1794.  
  1795.     \return
  1796.         This String after the append operation
  1797.  
  1798.     \exception std::length_error    Thrown if resulting String would be too long.
  1799.     */
  1800.     String& operator+=(utf32 code_point)
  1801.     {
  1802.         return append(1, code_point);
  1803.     }
  1804.  
  1805.     /*!
  1806.     \brief
  1807.         Appends a single code point multiple times to the string
  1808.  
  1809.     \param num
  1810.         Number of copies of the code point to be appended
  1811.  
  1812.     \param code_point
  1813.         utf32 Unicode code point that is to be appended
  1814.  
  1815.     \return
  1816.         This String after the append operation
  1817.  
  1818.     \exception std::length_error    Thrown if resulting String would be too long, or if \a num was 'npos'.
  1819.     */
  1820.     String& append(size_type num, utf32 code_point)
  1821.     {
  1822.         if (num == npos)
  1823.             throw std::length_error("Code point count can not be 'npos'");
  1824.  
  1825.         size_type newsz = d_cplength + num;
  1826.         grow(newsz);
  1827.  
  1828.         utf32* p = &ptr()[d_cplength];
  1829.  
  1830.         while(num--)
  1831.             *p++ = code_point;
  1832.  
  1833.         setlen(newsz);
  1834.  
  1835.         return *this;
  1836.     }
  1837.  
  1838.     /*!
  1839.     \brief
  1840.         Appends a single code point to the string
  1841.  
  1842.     \param code_point
  1843.         utf32 Unicode code point that is to be appended
  1844.  
  1845.     \return
  1846.         Nothing
  1847.  
  1848.     \exception std::length_error    Thrown if resulting String would be too long.
  1849.     */
  1850.     void    push_back(utf32 code_point)
  1851.     {
  1852.         append(1, code_point);
  1853.     }
  1854.  
  1855.     /*!
  1856.     \brief
  1857.         Appends the code points in the reange [beg, end)
  1858.  
  1859.     \param beg
  1860.         Iterator describing the start of the range to be appended
  1861.  
  1862.     \param end
  1863.         Iterator describing the (exclusive) end of the range to be appended.
  1864.  
  1865.     \return
  1866.         This String after the append operation
  1867.  
  1868.     \exception std::length_error    Thrown if the resulting string would be too large.
  1869.     */
  1870.     String&    append(const_iterator iter_beg, const_iterator iter_end)
  1871.     {
  1872.         return replace(end(), end(), iter_beg, iter_end);
  1873.     }
  1874.  
  1875.  
  1876.     /*!
  1877.     \brief
  1878.         Appends to the String the given c-string.
  1879.  
  1880.     \param c_str
  1881.         c-string that is to be appended.
  1882.  
  1883.     \return
  1884.         This String after the append operation
  1885.  
  1886.     \exception std::length_error    Thrown if resulting String would be too large.
  1887.     */
  1888.     String&    operator+=(const char* cstr)
  1889.     {
  1890.         return append(cstr, strlen(cstr));
  1891.     }
  1892.  
  1893.  
  1894.     /*!
  1895.     \brief
  1896.         Appends to the String the given c-string.
  1897.  
  1898.     \param c_str
  1899.         c-string that is to be appended.
  1900.  
  1901.     \return
  1902.         This String after the append operation
  1903.  
  1904.     \exception std::length_error    Thrown if resulting String would be too large.
  1905.     */
  1906.     String& append(const char* cstr)
  1907.     {
  1908.         return append(cstr, strlen(cstr));
  1909.     }
  1910.  
  1911.  
  1912.     /*!
  1913.     \brief
  1914.         Appends to the String chars from the given char array.
  1915.  
  1916.     \param chars
  1917.         char array holding the chars that are to be appended
  1918.  
  1919.     \param chars_len
  1920.         Number of chars to be appended
  1921.  
  1922.     \return
  1923.         This String after the append operation
  1924.  
  1925.     \exception std::length_error    Thrown if resulting String would be too large, or if \a chars_len was 'npos'
  1926.     */
  1927.     String& append(const char* chars, size_type chars_len)
  1928.     {
  1929.         if (chars_len == npos)
  1930.             throw std::length_error("Length for char array can not be 'npos'");
  1931.  
  1932.         size_type newsz = d_cplength + chars_len;
  1933.  
  1934.         grow(newsz);
  1935.  
  1936.         utf32* pt = &ptr()[newsz-1];
  1937.  
  1938.         while(chars_len--)
  1939.             *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
  1940.  
  1941.         setlen(newsz);
  1942.  
  1943.         return *this;
  1944.     }
  1945.  
  1946.  
  1947.     //////////////////////////////////////////////////////////////////////////
  1948.     // Insertion Functions
  1949.     //////////////////////////////////////////////////////////////////////////
  1950.     /*!
  1951.     \brief
  1952.         Inserts the given String object at the specified position.
  1953.  
  1954.     \param idx
  1955.         Index where the string is to be inserted.
  1956.  
  1957.     \param str
  1958.         String object that is to be inserted.
  1959.  
  1960.     \return
  1961.         This String after the insert.
  1962.  
  1963.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  1964.     \exception std::length_error    Thrown if resulting String would be too large.
  1965.     */
  1966.     String&    insert(size_type idx, const String& str)
  1967.     {
  1968.         return insert(idx, str, 0, npos);
  1969.     }
  1970.  
  1971.     /*!
  1972.     \brief
  1973.         Inserts a sub-string of the given String object at the specified position.
  1974.  
  1975.     \param idx
  1976.         Index where the string is to be inserted.
  1977.  
  1978.     \param str
  1979.         String object containing data to be inserted.
  1980.  
  1981.     \param str_idx
  1982.         Index of the first code point from \a str to be inserted.
  1983.  
  1984.     \param str_num
  1985.         Maximum number of code points from \a str to be inserted.
  1986.  
  1987.     \return
  1988.         This String after the insert.
  1989.  
  1990.     \exception std::out_of_range    Thrown if \a idx or \a str_idx are out of range.
  1991.     \exception std::length_error    Thrown if resulting String would be too large.
  1992.     */
  1993.     String& insert(size_type idx, const String& str, size_type str_idx, size_type str_num)
  1994.     {
  1995.         if ((d_cplength < idx) || (str.d_cplength < str_idx))
  1996.             throw std::out_of_range("Index is out of range for CEGUI::String");
  1997.  
  1998.         if (str_num == npos)
  1999.             str_num = str.d_cplength - str_idx;
  2000.  
  2001.         size_type newsz = d_cplength + str_num;
  2002.         grow(newsz);
  2003.         memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
  2004.         memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
  2005.         setlen(newsz);
  2006.  
  2007.         return *this;
  2008.     }
  2009.  
  2010.     /*!
  2011.     \brief
  2012.         Inserts the given std::string object at the specified position.
  2013.  
  2014.     \param idx
  2015.         Index where the std::string is to be inserted.
  2016.  
  2017.     \param std_str
  2018.         std::string object that is to be inserted.
  2019.  
  2020.     \note
  2021.         The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
  2022.         the provided data will occur.
  2023.  
  2024.     \return
  2025.         This String after the insert.
  2026.  
  2027.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  2028.     \exception std::length_error    Thrown if resulting String would be too large.
  2029.     */
  2030.     String&    insert(size_type idx, const std::string& std_str)
  2031.     {
  2032.         return insert(idx, std_str, 0, npos);
  2033.     }
  2034.  
  2035.     /*!
  2036.     \brief
  2037.         Inserts a sub-string of the given std::string object at the specified position.
  2038.  
  2039.     \param idx
  2040.         Index where the string is to be inserted.
  2041.  
  2042.     \param std_str
  2043.         std::string object containing data to be inserted.
  2044.  
  2045.     \note
  2046.         The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
  2047.         the provided data will occur.
  2048.  
  2049.     \param str_idx
  2050.         Index of the first character from \a std_str to be inserted.
  2051.  
  2052.     \param str_num
  2053.         Maximum number of characters from \a str to be inserted.
  2054.  
  2055.     \return
  2056.         This String after the insert.
  2057.  
  2058.     \exception std::out_of_range    Thrown if \a idx or \a str_idx are out of range.
  2059.     \exception std::length_error    Thrown if resulting String would be too large.
  2060.     */
  2061.     String& insert(size_type idx, const std::string& std_str, size_type str_idx, size_type str_num)
  2062.     {
  2063.         if (d_cplength < idx)
  2064.             throw std::out_of_range("Index is out of range for CEGUI::String");
  2065.  
  2066.         if (std_str.size() < str_idx)
  2067.             throw std::out_of_range("Index is out of range for std::string");
  2068.  
  2069.         if (str_num == npos)
  2070.             str_num = (size_type)std_str.size() - str_idx;
  2071.  
  2072.         size_type newsz = d_cplength + str_num;
  2073.         grow(newsz);
  2074.  
  2075.         memmove(&ptr()[idx + str_num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
  2076.  
  2077.         utf32* pt = &ptr()[idx + str_num - 1];
  2078.         
  2079.         while(str_num--)
  2080.             *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
  2081.  
  2082.         setlen(newsz);
  2083.  
  2084.         return *this;
  2085.     }
  2086.  
  2087.     /*!
  2088.     \brief
  2089.         Inserts the given null-terminated utf8 encoded data at the specified position.
  2090.  
  2091.     \param idx
  2092.         Index where the data is to be inserted.
  2093.  
  2094.     \param utf8_str
  2095.         Buffer containing the null-terminated utf8 encoded data that is to be inserted.
  2096.  
  2097.     \note
  2098.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  2099.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  2100.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  2101.         results.
  2102.  
  2103.     \return
  2104.         This String after the insert.
  2105.  
  2106.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  2107.     \exception std::length_error    Thrown if resulting String would be too large.
  2108.     */
  2109.     String&    insert(size_type idx, const utf8* utf8_str)
  2110.     {
  2111.         return insert(idx, utf8_str, utf_length(utf8_str));
  2112.     }
  2113.  
  2114.     /*!
  2115.     \brief
  2116.         Inserts the given utf8 encoded data at the specified position.
  2117.  
  2118.     \param idx
  2119.         Index where the data is to be inserted.
  2120.  
  2121.     \param utf8_str
  2122.         Buffer containing the utf8 encoded data that is to be inserted.
  2123.  
  2124.     \note
  2125.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  2126.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  2127.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  2128.         results.
  2129.  
  2130.     \param len
  2131.         Length of the data to be inserted in uf8 code units (not code points)
  2132.  
  2133.     \return
  2134.         This String after the insert.
  2135.  
  2136.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  2137.     \exception std::length_error    Thrown if resulting String would be too large, or if \a len is 'npos'
  2138.     */
  2139.     String& insert(size_type idx, const utf8* utf8_str, size_type len)
  2140.     {
  2141.         if (d_cplength < idx)
  2142.             throw std::out_of_range("Index is out of range for CEGUI::String");
  2143.  
  2144.         if (len == npos)
  2145.             throw std::length_error("Length of utf8 encoded string can not be 'npos'");
  2146.  
  2147.         size_type encsz = encoded_size(utf8_str, len);
  2148.         size_type newsz = d_cplength + encsz;
  2149.  
  2150.         grow(newsz);
  2151.         memmove(&ptr()[idx + encsz], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
  2152.         encode(utf8_str, &ptr()[idx], encsz, len);
  2153.         setlen(newsz);
  2154.  
  2155.         return *this;
  2156.     }
  2157.  
  2158.     /*!
  2159.     \brief
  2160.         Inserts a code point multiple times into the String
  2161.  
  2162.     \param idx
  2163.         Index where the code point(s) are to be inserted
  2164.  
  2165.     \param num
  2166.         The number of times to insert the code point
  2167.  
  2168.     \param code_point
  2169.         The utf32 code point that is to be inserted
  2170.  
  2171.     \return
  2172.         This String after the insertion.
  2173.  
  2174.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  2175.     \exception std::length_error    Thrown if resulting String would be too large, or if \a num is 'npos'
  2176.     */
  2177.     String& insert(size_type idx, size_type num, utf32 code_point)
  2178.     {
  2179.         if (d_cplength < idx)
  2180.             throw std::out_of_range("Index is out of range for CEGUI::String");
  2181.  
  2182.         if (num == npos)
  2183.             throw std::length_error("Code point count can not be 'npos'");
  2184.  
  2185.         size_type newsz = d_cplength + num;
  2186.         grow(newsz);
  2187.  
  2188.         memmove(&ptr()[idx + num], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
  2189.  
  2190.         utf32* pt = &ptr()[idx + num - 1];
  2191.  
  2192.         while(num--)
  2193.             *pt-- = code_point;
  2194.  
  2195.         setlen(newsz);
  2196.  
  2197.         return *this;
  2198.     }
  2199.  
  2200.     /*!
  2201.     \brief
  2202.         Inserts a code point multiple times into the String
  2203.  
  2204.     \param pos
  2205.         Iterator describing the position where the code point(s) are to be inserted
  2206.  
  2207.     \param num
  2208.         The number of times to insert the code point
  2209.  
  2210.     \param code_point
  2211.         The utf32 code point that is to be inserted
  2212.  
  2213.     \return
  2214.         This String after the insertion.
  2215.  
  2216.     \exception std::length_error    Thrown if resulting String would be too large, or if \a num is 'npos'
  2217.     */
  2218.     void insert(iterator pos, size_type num, utf32 code_point)
  2219.     {
  2220.         insert(safe_iter_dif(pos, begin()), num, code_point);
  2221.     }
  2222.  
  2223.     /*!
  2224.     \brief
  2225.         Inserts a single code point into the String
  2226.  
  2227.     \param pos
  2228.         Iterator describing the position where the code point is to be inserted
  2229.  
  2230.     \param code_point
  2231.         The utf32 code point that is to be inserted
  2232.  
  2233.     \return
  2234.         This String after the insertion.
  2235.  
  2236.     \exception std::length_error    Thrown if resulting String would be too large.
  2237.     */
  2238.     iterator insert(iterator pos, utf32 code_point)
  2239.     {
  2240.         insert(pos, 1, code_point);
  2241.         return pos;
  2242.     }
  2243.  
  2244.     /*!
  2245.     \brief
  2246.         Inserts code points specified by the range [beg, end).
  2247.  
  2248.     \param pos
  2249.         Iterator describing the position where the data is to be inserted
  2250.  
  2251.     \param beg
  2252.         Iterator describing the begining of the range to be inserted
  2253.  
  2254.     \param end
  2255.         Iterator describing the (exclusive) end of the range to be inserted.
  2256.  
  2257.     \return
  2258.         Nothing.
  2259.  
  2260.     \exception std::length_error    Thrown if resulting String would be too large.
  2261.     */
  2262.     void    insert(iterator iter_pos, const_iterator iter_beg, const_iterator iter_end)
  2263.     {
  2264.         replace(iter_pos, iter_pos, iter_beg, iter_end);
  2265.     }
  2266.  
  2267.  
  2268.     /*!
  2269.     \brief
  2270.         Inserts the given c-string at the specified position.
  2271.  
  2272.     \param idx
  2273.         Index where the c-string is to be inserted.
  2274.  
  2275.     \param c_str
  2276.         c-string that is to be inserted.
  2277.  
  2278.     \return
  2279.         This String after the insert.
  2280.  
  2281.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  2282.     \exception std::length_error    Thrown if resulting String would be too large.
  2283.     */
  2284.     String&    insert(size_type idx, const char* cstr)
  2285.     {
  2286.         return insert(idx, cstr, strlen(cstr));
  2287.     }
  2288.  
  2289.  
  2290.     /*!
  2291.     \brief
  2292.         Inserts chars from the given char array at the specified position.
  2293.  
  2294.     \param idx
  2295.         Index where the data is to be inserted.
  2296.  
  2297.     \param chars
  2298.         char array containing the chars that are to be inserted.
  2299.  
  2300.     \param chars_len
  2301.         Length of the char array to be inserted.
  2302.  
  2303.     \return
  2304.         This String after the insert.
  2305.  
  2306.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  2307.     \exception std::length_error    Thrown if resulting String would be too large, or if \a chars_len is 'npos'
  2308.     */
  2309.     String& insert(size_type idx, const char* chars, size_type chars_len)
  2310.     {
  2311.         if (d_cplength < idx)
  2312.             throw std::out_of_range("Index is out of range for CEGUI::String");
  2313.  
  2314.         if (chars_len == npos)
  2315.             throw std::length_error("Length of char array can not be 'npos'");
  2316.  
  2317.         size_type newsz = d_cplength + chars_len;
  2318.  
  2319.         grow(newsz);
  2320.         memmove(&ptr()[idx + chars_len], &ptr()[idx], (d_cplength - idx) * sizeof(utf32));
  2321.  
  2322.         utf32* pt = &ptr()[idx + chars_len - 1];
  2323.  
  2324.         while(chars_len--)
  2325.             *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
  2326.  
  2327.         setlen(newsz);
  2328.  
  2329.         return *this;
  2330.     }
  2331.  
  2332.  
  2333.     //////////////////////////////////////////////////////////////////////////
  2334.     // Erasing characters
  2335.     //////////////////////////////////////////////////////////////////////////
  2336.     /*!
  2337.     \brief
  2338.         Removes all data from the String
  2339.  
  2340.     \return
  2341.         Nothing
  2342.     */
  2343.     void    clear(void)
  2344.     {
  2345.         setlen(0);
  2346.         trim();
  2347.     }
  2348.  
  2349.     /*!
  2350.     \brief
  2351.         Removes all data from the String
  2352.  
  2353.     \return
  2354.         The empty String (*this)
  2355.     */
  2356.     String& erase(void)
  2357.     {
  2358.         clear();
  2359.         return *this;
  2360.     }
  2361.  
  2362.     /*!
  2363.     \brief
  2364.         Erase a single code point from the string
  2365.  
  2366.     \param idx
  2367.         The index of the code point to be removed.
  2368.  
  2369.     \return
  2370.         This String after the erase operation
  2371.  
  2372.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  2373.     */
  2374.     String&    erase(size_type idx)
  2375.     {
  2376.         return erase(idx, 1);
  2377.     }
  2378.  
  2379.     /*!
  2380.     \brief
  2381.         Erase a range of code points
  2382.  
  2383.     \param idx
  2384.         Index of the first code point to be removed.
  2385.  
  2386.     \param len
  2387.         Maximum number of code points to be removed.
  2388.  
  2389.     \return
  2390.         This String after the erase operation.
  2391.  
  2392.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  2393.     */
  2394.     String& erase(size_type idx, size_type len = npos)
  2395.     {
  2396.         if (d_cplength < idx)
  2397.             throw std::out_of_range("Index is out of range foe CEGUI::String");
  2398.  
  2399.         if (len == npos)
  2400.             len = d_cplength - idx;
  2401.  
  2402.         size_type newsz = d_cplength - len;
  2403.  
  2404.         memmove(&ptr()[idx], &ptr()[idx + len], (d_cplength - idx - len) * sizeof(utf32));
  2405.         setlen(newsz);
  2406.         return    *this;
  2407.     }
  2408.  
  2409.     /*!
  2410.     \brief
  2411.         Erase the code point described by the given iterator
  2412.  
  2413.     \param pos
  2414.         Iterator describing the code point to be erased
  2415.  
  2416.     \return
  2417.         This String after the erase operation.
  2418.     */
  2419.     String& erase(iterator pos)
  2420.     {
  2421.         return erase(safe_iter_dif(pos, begin()), 1);
  2422.     }
  2423.  
  2424.     /*!
  2425.     \brief
  2426.         Erase a range of code points described by the iterators [beg, end).
  2427.  
  2428.     \param beg
  2429.         Iterator describing the postion of the beginning of the range to erase
  2430.  
  2431.     \param end
  2432.         Iterator describing the postion of the (exclusive) end of the range to erase
  2433.  
  2434.     \return
  2435.         This String after the erase operation.
  2436.     */
  2437.     String& erase(iterator iter_beg, iterator iter_end)
  2438.     {
  2439.         return erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
  2440.     }
  2441.  
  2442.     //////////////////////////////////////////////////////////////////////////
  2443.     // Resizing
  2444.     //////////////////////////////////////////////////////////////////////////
  2445.     /*!
  2446.     \brief
  2447.         Resizes the String either by inserting default utf32 code points to make it larger, or by truncating to make it smaller
  2448.  
  2449.     \param num
  2450.         The length, in code points, that the String is to be made.
  2451.  
  2452.     \return
  2453.         Nothing.
  2454.  
  2455.     \exception std::length_error    Thrown if the String would be too large.
  2456.     */
  2457.     void    resize(size_type num)
  2458.     {
  2459.         resize(num, utf32());
  2460.     }
  2461.  
  2462.     /*!
  2463.     \brief
  2464.         Resizes the String either by inserting the given utf32 code point to make it larger, or by truncating to make it smaller
  2465.  
  2466.     \param num
  2467.         The length, in code points, that the String is to be made.
  2468.  
  2469.     \param code_point
  2470.         The utf32 code point that should be used when majing the String larger
  2471.  
  2472.     \return
  2473.         Nothing.
  2474.  
  2475.     \exception std::length_error    Thrown if the String would be too large.
  2476.     */
  2477.     void    resize(size_type num, utf32 code_point)
  2478.     {
  2479.         if (num < d_cplength)
  2480.         {
  2481.             setlen(num);
  2482.         }
  2483.         else
  2484.         {
  2485.             append(num - d_cplength, code_point);
  2486.         }
  2487.  
  2488.     }
  2489.  
  2490.     //////////////////////////////////////////////////////////////////////////
  2491.     // Replacing Characters
  2492.     //////////////////////////////////////////////////////////////////////////
  2493.     /*!
  2494.     \brief
  2495.         Replace code points in the String with the specified String object
  2496.  
  2497.     \param idx
  2498.         Index of the first code point to be replaced
  2499.  
  2500.     \param len
  2501.         Maximum number of code points to be replaced (if this is 0, operation is an insert at position \a idx)
  2502.  
  2503.     \param str
  2504.         The String object that is to replace the specified code points
  2505.  
  2506.     \return
  2507.         This String after the replace operation
  2508.  
  2509.     \exception std::out_of_range    Thrown if \a idx is invalid for this String
  2510.     \exception std::length_error    Thrown if the resulting String would be too large.
  2511.     */
  2512.     String& replace(size_type idx, size_type len, const String& str)
  2513.     {
  2514.         return replace(idx, len, str, 0, npos);
  2515.     }
  2516.  
  2517.     /*!
  2518.     \brief
  2519.         Replace the code points in the range [beg, end) with the specified String object
  2520.  
  2521.     \note
  2522.         If \a beg == \a end, the operation is a insert at iterator position \a beg
  2523.  
  2524.     \param beg
  2525.         Iterator describing the start of the range to be replaced
  2526.  
  2527.     \param end
  2528.         Iterator describing the (exclusive) end of the range to be replaced.
  2529.  
  2530.     \param str
  2531.         The String object that is to replace the specified range of code points
  2532.  
  2533.     \return
  2534.         This String after the replace operation
  2535.  
  2536.     \exception std::length_error    Thrown if the resulting String would be too large.
  2537.     */
  2538.     String& replace(iterator iter_beg, iterator iter_end, const String& str)
  2539.     {
  2540.         return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), str, 0, npos);
  2541.     }
  2542.  
  2543.     /*!
  2544.     \brief
  2545.         Replace code points in the String with a specified sub-string of a given String object.
  2546.  
  2547.     \param idx
  2548.         Index of the first code point to be replaced
  2549.  
  2550.     \param len
  2551.         Maximum number of code points to be replaced.  If this is 0, the operation is an insert at position \a idx.
  2552.  
  2553.     \param str
  2554.         String object containing the data that will replace the specified range of code points
  2555.  
  2556.     \param str_idx
  2557.         Index of the first code point of \a str that is to replace the specified code point range
  2558.  
  2559.     \param str_num
  2560.         Maximum number of code points of \a str that are to replace the specified code point range
  2561.  
  2562.     \return
  2563.         This String after the replace operation
  2564.  
  2565.     \exception std::out_of_range    Thrown if either \a idx, or \a str_idx are invalid
  2566.     \exception std::length_error    Thrown if the resulting String would have been too large.
  2567.     */
  2568.     String& replace(size_type idx, size_type len, const String& str, size_type str_idx, size_type str_num)
  2569.     {
  2570.         if ((d_cplength < idx) || (str.d_cplength < str_idx))
  2571.             throw std::out_of_range("Index is out of range for CEGUI::String");
  2572.  
  2573.         if (((str_idx + str_num) > str.d_cplength) || (str_num == npos))
  2574.             str_num = str.d_cplength - str_idx;
  2575.  
  2576.         if (((len + idx) > d_cplength) || (len == npos))
  2577.             len = d_cplength - idx;
  2578.  
  2579.         size_type newsz = d_cplength + str_num - len;
  2580.  
  2581.         grow(newsz);
  2582.  
  2583.         if ((idx + len) < d_cplength)
  2584.             memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
  2585.  
  2586.         memcpy(&ptr()[idx], &str.ptr()[str_idx], str_num * sizeof(utf32));
  2587.         setlen(newsz);
  2588.  
  2589.         return *this;
  2590.     }
  2591.  
  2592.  
  2593.     /*!
  2594.     \brief
  2595.         Replace code points in the String with the specified std::string object
  2596.  
  2597.     \param idx
  2598.         Index of the first code point to be replaced
  2599.  
  2600.     \param len
  2601.         Maximum number of code points to be replaced (if this is 0, operation is an insert at position \a idx)
  2602.  
  2603.     \param std_str
  2604.         The std::string object that is to replace the specified code points
  2605.  
  2606.     \note
  2607.         Characters from \a std_str are considered to represent Unicode code points in the range 0x00..0xFF.  No translation of
  2608.         the encountered data is performed.
  2609.  
  2610.     \return
  2611.         This String after the replace operation
  2612.  
  2613.     \exception std::out_of_range    Thrown if \a idx is invalid for this String
  2614.     \exception std::length_error    Thrown if the resulting String would be too large.
  2615.     */
  2616.     String& replace(size_type idx, size_type len, const std::string& std_str)
  2617.     {
  2618.         return replace(idx, len, std_str, 0, npos);
  2619.     }
  2620.  
  2621.     /*!
  2622.     \brief
  2623.         Replace the code points in the range [beg, end) with the specified std::string object
  2624.  
  2625.     \note
  2626.         If \a beg == \a end, the operation is a insert at iterator position \a beg
  2627.  
  2628.     \param beg
  2629.         Iterator describing the start of the range to be replaced
  2630.  
  2631.     \param end
  2632.         Iterator describing the (exclusive) end of the range to be replaced.
  2633.  
  2634.     \param std_str
  2635.         The std::string object that is to replace the specified range of code points
  2636.  
  2637.     \note
  2638.         Characters from \a std_str are considered to represent Unicode code points in the range 0x00..0xFF.  No translation of
  2639.         the encountered data is performed.
  2640.  
  2641.     \return
  2642.         This String after the replace operation
  2643.  
  2644.     \exception std::length_error    Thrown if the resulting String would be too large.
  2645.     */
  2646.     String& replace(iterator iter_beg, iterator iter_end, const std::string& std_str)
  2647.     {
  2648.         return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), std_str, 0, npos);
  2649.     }
  2650.  
  2651.     /*!
  2652.     \brief
  2653.         Replace code points in the String with a specified sub-string of a given std::string object.
  2654.  
  2655.     \param idx
  2656.         Index of the first code point to be replaced
  2657.  
  2658.     \param len
  2659.         Maximum number of code points to be replaced.  If this is 0, the operation is an insert at position \a idx.
  2660.  
  2661.     \param std_str
  2662.         std::string object containing the data that will replace the specified range of code points
  2663.  
  2664.     \note
  2665.         Characters from \a std_str are considered to represent Unicode code points in the range 0x00..0xFF.  No translation of
  2666.         the encountered data is performed.
  2667.  
  2668.     \param str_idx
  2669.         Index of the first code point of \a std_str that is to replace the specified code point range
  2670.  
  2671.     \param str_num
  2672.         Maximum number of code points of \a std_str that are to replace the specified code point range
  2673.  
  2674.     \return
  2675.         This String after the replace operation
  2676.  
  2677.     \exception std::out_of_range    Thrown if either \a idx, or \a str_idx are invalid
  2678.     \exception std::length_error    Thrown if the resulting String would have been too large.
  2679.     */
  2680.     String& replace(size_type idx, size_type len, const std::string& std_str, size_type str_idx, size_type str_num)
  2681.     {
  2682.         if (d_cplength < idx)
  2683.             throw std::out_of_range("Index is out of range for CEGUI::String");
  2684.  
  2685.         if (std_str.size() < str_idx)
  2686.             throw std::out_of_range("Index is out of range for std::string");
  2687.  
  2688.         if (((str_idx + str_num) > std_str.size()) || (str_num == npos))
  2689.             str_num = (size_type)std_str.size() - str_idx;
  2690.  
  2691.         if (((len + idx) > d_cplength) || (len == npos))
  2692.             len = d_cplength - idx;
  2693.  
  2694.         size_type newsz = d_cplength + str_num - len;
  2695.  
  2696.         grow(newsz);
  2697.  
  2698.         if ((idx + len) < d_cplength)
  2699.             memmove(&ptr()[idx + str_num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
  2700.  
  2701.         utf32* pt = &ptr()[idx + str_num - 1];
  2702.  
  2703.         while (str_num--)
  2704.             *pt-- = static_cast<utf32>(static_cast<unsigned char>(std_str[str_idx + str_num]));
  2705.  
  2706.         setlen(newsz);
  2707.  
  2708.         return *this;
  2709.     }
  2710.  
  2711.  
  2712.     /*!
  2713.     \brief
  2714.         Replace code points in the String with the specified null-terminated utf8 encoded data.
  2715.  
  2716.     \param idx
  2717.         Index of the first code point to be replaced
  2718.  
  2719.     \param len
  2720.         Maximum number of code points to be replaced (if this is 0, operation is an insert at position \a idx)
  2721.  
  2722.     \param utf8_str
  2723.         Buffer containing the null-terminated utf8 encoded data that is to replace the specified code points
  2724.  
  2725.     \note
  2726.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  2727.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  2728.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  2729.         results.
  2730.  
  2731.     \return
  2732.         This String after the replace operation
  2733.  
  2734.     \exception std::out_of_range    Thrown if \a idx is invalid for this String
  2735.     \exception std::length_error    Thrown if the resulting String would be too large.
  2736.     */
  2737.     String& replace(size_type idx, size_type len, const utf8* utf8_str)
  2738.     {
  2739.         return replace(idx, len, utf8_str, utf_length(utf8_str));
  2740.     }
  2741.  
  2742.     /*!
  2743.     \brief
  2744.         Replace the code points in the range [beg, end) with the specified null-terminated utf8 encoded data.
  2745.  
  2746.     \note
  2747.         If \a beg == \a end, the operation is a insert at iterator position \a beg
  2748.  
  2749.     \param beg
  2750.         Iterator describing the start of the range to be replaced
  2751.  
  2752.     \param end
  2753.         Iterator describing the (exclusive) end of the range to be replaced.
  2754.  
  2755.     \param utf8_str
  2756.         Buffer containing the null-terminated utf8 encoded data that is to replace the specified range of code points
  2757.  
  2758.     \note
  2759.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  2760.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  2761.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  2762.         results.
  2763.  
  2764.     \return
  2765.         This String after the replace operation
  2766.  
  2767.     \exception std::length_error    Thrown if the resulting String would be too large.
  2768.     */
  2769.     String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str)
  2770.     {
  2771.         return replace(iter_beg, iter_end, utf8_str, utf_length(utf8_str));
  2772.     }
  2773.  
  2774.     /*!
  2775.     \brief
  2776.         Replace code points in the String with the specified utf8 encoded data.
  2777.  
  2778.     \param idx
  2779.         Index of the first code point to be replaced
  2780.  
  2781.     \param len
  2782.         Maximum number of code points to be replaced (if this is 0, operation is an insert at position \a idx)
  2783.  
  2784.     \param utf8_str
  2785.         Buffer containing the null-terminated utf8 encoded data that is to replace the specified code points
  2786.  
  2787.     \note
  2788.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  2789.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  2790.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  2791.         results.
  2792.  
  2793.     \param str_len
  2794.         Length of the utf8 encoded data in utf8 code units (not code points).
  2795.  
  2796.     \return
  2797.         This String after the replace operation
  2798.  
  2799.     \exception std::out_of_range    Thrown if \a idx is invalid for this String
  2800.     \exception std::length_error    Thrown if the resulting String would be too large, or if \a str_len was 'npos'.
  2801.     */
  2802.     String& replace(size_type idx, size_type len, const utf8* utf8_str, size_type str_len)
  2803.     {
  2804.         if (d_cplength < idx)
  2805.             throw std::out_of_range("Index is out of range for CEGUI::String");
  2806.  
  2807.         if (str_len == npos)
  2808.             throw std::length_error("Length for utf8 encoded string can not be 'npos'");
  2809.  
  2810.         if (((len + idx) > d_cplength) || (len == npos))
  2811.             len = d_cplength - idx;
  2812.  
  2813.         size_type encsz = encoded_size(utf8_str, str_len);
  2814.         size_type newsz = d_cplength + encsz - len;
  2815.  
  2816.         grow(newsz);
  2817.  
  2818.         if ((idx + len) < d_cplength)
  2819.             memmove(&ptr()[idx + encsz], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
  2820.  
  2821.         encode(utf8_str, &ptr()[idx], encsz, str_len);
  2822.  
  2823.         setlen(newsz);
  2824.         return *this;
  2825.     }
  2826.  
  2827.     /*!
  2828.     \brief
  2829.         Replace the code points in the range [beg, end) with the specified null-terminated utf8 encoded data.
  2830.  
  2831.     \note
  2832.         If \a beg == \a end, the operation is a insert at iterator position \a beg
  2833.  
  2834.     \param beg
  2835.         Iterator describing the start of the range to be replaced
  2836.  
  2837.     \param end
  2838.         Iterator describing the (exclusive) end of the range to be replaced.
  2839.  
  2840.     \param utf8_str
  2841.         Buffer containing the null-terminated utf8 encoded data that is to replace the specified range of code points
  2842.  
  2843.     \note
  2844.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  2845.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  2846.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  2847.         results.
  2848.  
  2849.     \param str_len
  2850.         Length of the utf8 encoded data in utf8 code units (not code points).
  2851.  
  2852.     \return
  2853.         This String after the replace operation
  2854.  
  2855.         \exception std::length_error    Thrown if the resulting String would be too large, or if \a str_len was 'npos'.
  2856.     */
  2857.     String& replace(iterator iter_beg, iterator iter_end, const utf8* utf8_str, size_type str_len)
  2858.     {
  2859.         return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), utf8_str, str_len);
  2860.     }
  2861.  
  2862.     /*!
  2863.     \brief
  2864.         Replaces a specified range of code points with occurrences of a given code point
  2865.  
  2866.     \param idx
  2867.         Index of the first code point to be replaced
  2868.  
  2869.     \param len
  2870.         Maximum number of code points to replace.  If this is 0 the operation is an insert
  2871.  
  2872.     \param num
  2873.         Number of occurrences of \a code_point that are to replace the specified range of code points
  2874.  
  2875.     \param code_point
  2876.         Code point that is to be used when replacing the specified range of code points
  2877.  
  2878.     \return
  2879.         This String after the replace operation.
  2880.  
  2881.     \exception std::out_of_range    Thrown if \a idx is invalid for this String
  2882.     \exception std::length_error    Thrown if resulting String would have been too long, or if \a num was 'npos'.
  2883.     */
  2884.     String& replace(size_type idx, size_type len, size_type num, utf32 code_point)
  2885.     {
  2886.         if (d_cplength < idx)
  2887.             throw std::out_of_range("Index is out of range for CEGUI::String");
  2888.  
  2889.         if (num == npos)
  2890.             throw std::length_error("Code point count can not be 'npos'");
  2891.  
  2892.         if (((len + idx) > d_cplength) || (len == npos))
  2893.             len = d_cplength - idx;
  2894.  
  2895.         size_type newsz = d_cplength + num - len;
  2896.  
  2897.         grow(newsz);
  2898.  
  2899.         if ((idx + len) < d_cplength)
  2900.             memmove(&ptr()[idx + num], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
  2901.  
  2902.         utf32* pt = &ptr()[idx + num - 1];
  2903.  
  2904.         while (num--)
  2905.             *pt-- = code_point;
  2906.  
  2907.         setlen(newsz);
  2908.  
  2909.         return *this;
  2910.     }
  2911.  
  2912.     /*!
  2913.     \brief
  2914.         Replace the code points in the range [beg, end) with occurrences of a given code point
  2915.  
  2916.     \note
  2917.         If \a beg == \a end, the operation is an insert at iterator position \a beg
  2918.  
  2919.     \param beg
  2920.         Iterator describing the start of the range to be replaced
  2921.  
  2922.     \param end
  2923.         Iterator describing the (exclusive) end of the range to be replaced.
  2924.  
  2925.     \param num
  2926.         Number of occurrences of \a code_point that are to replace the specified range of code points
  2927.  
  2928.     \param code_point
  2929.         Code point that is to be used when replacing the specified range of code points
  2930.  
  2931.     \return
  2932.         This String after the replace operation
  2933.  
  2934.     \exception std::length_error    Thrown if resulting String would have been too long, or if \a num was 'npos'.
  2935.     */
  2936.     String& replace(iterator iter_beg, iterator iter_end, size_type num, utf32 code_point)
  2937.     {
  2938.         return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), num, code_point);
  2939.     }
  2940.  
  2941.  
  2942.     /*!
  2943.     \brief
  2944.         Replace the code points in the range [beg, end) with code points from the range [newBeg, newEnd).
  2945.  
  2946.     \note
  2947.         If \a beg == \a end, the operation is an insert at iterator position \a beg
  2948.  
  2949.     \param beg
  2950.         Iterator describing the start of the range to be replaced
  2951.  
  2952.     \param end
  2953.         Iterator describing the (exclusive) end of the range to be replaced.
  2954.  
  2955.     \param newBeg
  2956.         Iterator describing the beginning of the range to insert.
  2957.  
  2958.     \param newEnd    
  2959.         Iterator describing the (exclusive) end of the range to insert.
  2960.  
  2961.     \return
  2962.         This String after the insert operation.
  2963.  
  2964.     \exception std::length_error    Thrown if the resulting string would be too long.
  2965.     */
  2966.     String& replace(iterator iter_beg, iterator iter_end, const_iterator iter_newBeg, const_iterator iter_newEnd)
  2967.     {
  2968.         if (iter_beg == iter_end)
  2969.         {
  2970.             erase(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg));
  2971.         }
  2972.         else
  2973.         {
  2974.             size_type str_len = safe_iter_dif(iter_newEnd, iter_newBeg);
  2975.             size_type idx = safe_iter_dif(iter_beg, begin());
  2976.             size_type len = safe_iter_dif(iter_end, iter_beg);
  2977.  
  2978.             if ((len + idx) > d_cplength)
  2979.                 len = d_cplength - idx;
  2980.  
  2981.             size_type newsz = d_cplength + str_len - len;
  2982.  
  2983.             grow(newsz);
  2984.  
  2985.             if ((idx + len) < d_cplength)
  2986.                 memmove(&ptr()[idx + str_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
  2987.  
  2988.             memcpy(&ptr()[idx], iter_newBeg.d_ptr, str_len * sizeof(utf32));
  2989.             setlen(newsz);
  2990.         }
  2991.  
  2992.         return *this;
  2993.     }
  2994.  
  2995.  
  2996.     /*!
  2997.     \brief
  2998.         Replace code points in the String with the specified c-string.
  2999.  
  3000.     \param idx
  3001.         Index of the first code point to be replaced
  3002.  
  3003.     \param len
  3004.         Maximum number of code points to be replaced (if this is 0, operation is an insert at position \a idx)
  3005.  
  3006.     \param c_str
  3007.         c-string that is to replace the specified code points
  3008.  
  3009.     \return
  3010.         This String after the replace operation
  3011.  
  3012.     \exception std::out_of_range    Thrown if \a idx is invalid for this String
  3013.     \exception std::length_error    Thrown if the resulting String would be too large.
  3014.     */
  3015.     String& replace(size_type idx, size_type len, const char* cstr)
  3016.     {
  3017.         return replace(idx, len, cstr, strlen(cstr));
  3018.     }
  3019.  
  3020.  
  3021.     /*!
  3022.     \brief
  3023.         Replace the code points in the range [beg, end) with the specified c-string.
  3024.  
  3025.     \note
  3026.         If \a beg == \a end, the operation is a insert at iterator position \a beg
  3027.  
  3028.     \param beg
  3029.         Iterator describing the start of the range to be replaced
  3030.  
  3031.     \param end
  3032.         Iterator describing the (exclusive) end of the range to be replaced.
  3033.  
  3034.     \param c_str
  3035.         c-string that is to replace the specified range of code points
  3036.  
  3037.     \return
  3038.         This String after the replace operation
  3039.  
  3040.     \exception std::length_error    Thrown if the resulting String would be too large.
  3041.     */
  3042.     String& replace(iterator iter_beg, iterator iter_end, const char* cstr)
  3043.     {
  3044.         return replace(iter_beg, iter_end, cstr, strlen(cstr));
  3045.     }
  3046.  
  3047.  
  3048.     /*!
  3049.     \brief
  3050.         Replace code points in the String with chars from the given char array.
  3051.  
  3052.     \param idx
  3053.         Index of the first code point to be replaced
  3054.  
  3055.     \param len
  3056.         Maximum number of code points to be replaced (if this is 0, operation is an insert at position \a idx)
  3057.  
  3058.     \param chars
  3059.         char array containing the cars that are to replace the specified code points
  3060.  
  3061.     \param chars_len
  3062.         Number of chars in the char array.
  3063.  
  3064.     \return
  3065.         This String after the replace operation
  3066.  
  3067.     \exception std::out_of_range    Thrown if \a idx is invalid for this String
  3068.     \exception std::length_error    Thrown if the resulting String would be too large, or if \a chars_len was 'npos'.
  3069.     */
  3070.     String& replace(size_type idx, size_type len, const char* chars, size_type chars_len)
  3071.     {
  3072.         if (d_cplength < idx)
  3073.             throw std::out_of_range("Index is out of range for CEGUI::String");
  3074.  
  3075.         if (chars_len == npos)
  3076.             throw std::length_error("Length for the char array can not be 'npos'");
  3077.  
  3078.         if (((len + idx) > d_cplength) || (len == npos))
  3079.             len = d_cplength - idx;
  3080.  
  3081.         size_type newsz = d_cplength + chars_len - len;
  3082.  
  3083.         grow(newsz);
  3084.  
  3085.         if ((idx + len) < d_cplength)
  3086.             memmove(&ptr()[idx + chars_len], &ptr()[len + idx], (d_cplength - idx - len) * sizeof(utf32));
  3087.  
  3088.         utf32* pt = &ptr()[idx + chars_len - 1];
  3089.  
  3090.         while (chars_len--)
  3091.             *pt-- = static_cast<utf32>(static_cast<unsigned char>(chars[chars_len]));
  3092.  
  3093.         setlen(newsz);
  3094.         return *this;
  3095.     }
  3096.  
  3097.  
  3098.     /*!
  3099.     \brief
  3100.         Replace the code points in the range [beg, end) with chars from the given char array.
  3101.  
  3102.     \note
  3103.         If \a beg == \a end, the operation is a insert at iterator position \a beg
  3104.  
  3105.     \param beg
  3106.         Iterator describing the start of the range to be replaced
  3107.  
  3108.     \param end
  3109.         Iterator describing the (exclusive) end of the range to be replaced.
  3110.  
  3111.     \param chars
  3112.         char array containing the chars that are to replace the specified range of code points
  3113.  
  3114.     \param chars_len
  3115.         Number of chars in the char array.
  3116.  
  3117.     \return
  3118.         This String after the replace operation
  3119.  
  3120.     \exception std::length_error    Thrown if the resulting String would be too large, or if \a chars_len was 'npos'.
  3121.     */
  3122.     String& replace(iterator iter_beg, iterator iter_end, const char* chars, size_type chars_len)
  3123.     {
  3124.         return replace(safe_iter_dif(iter_beg, begin()), safe_iter_dif(iter_end, iter_beg), chars, chars_len);
  3125.     }
  3126.  
  3127.  
  3128.     //////////////////////////////////////////////////////////////////////////
  3129.     // Find a code point
  3130.     //////////////////////////////////////////////////////////////////////////
  3131.     /*!
  3132.     \brief
  3133.         Search forwards for a given code point
  3134.  
  3135.     \param code_point
  3136.         The utf32 code point to search for
  3137.  
  3138.     \param idx
  3139.         Index of the code point where the search is to start.
  3140.  
  3141.     \return
  3142.         - Index of the first occurrence of \a code_point travelling forwards from \a idx.
  3143.         - npos if the code point could not be found
  3144.     */
  3145.     size_type    find(utf32 code_point, size_type idx = 0) const
  3146.     {
  3147.         if (idx < d_cplength)
  3148.         {
  3149.             const utf32* pt = &ptr()[idx];
  3150.  
  3151.             while (idx < d_cplength)
  3152.             {
  3153.                 if (*pt++ == code_point)
  3154.                     return idx;
  3155.  
  3156.                 ++idx;
  3157.             }
  3158.  
  3159.         }
  3160.  
  3161.         return npos;
  3162.     }
  3163.  
  3164.     /*!
  3165.     \brief
  3166.         Search backwards for a given code point
  3167.  
  3168.     \param code_point
  3169.         The utf32 code point to search for
  3170.  
  3171.     \param idx
  3172.         Index of the code point where the search is to start.
  3173.  
  3174.     \return
  3175.         - Index of the first occurrence of \a code_point travelling backwards from \a idx.
  3176.         - npos if the code point could not be found
  3177.     */
  3178.     size_type    rfind(utf32 code_point, size_type idx = npos) const
  3179.     {
  3180.         if (idx >= d_cplength)
  3181.             idx = d_cplength - 1;
  3182.  
  3183.         if (d_cplength > 0)
  3184.         {
  3185.             const utf32* pt = &ptr()[idx];
  3186.  
  3187.             do
  3188.             {
  3189.                 if (*pt-- == code_point)
  3190.                     return idx;
  3191.  
  3192.             } while (idx-- != 0);
  3193.  
  3194.         }
  3195.  
  3196.         return npos;
  3197.     }
  3198.  
  3199.     //////////////////////////////////////////////////////////////////////////
  3200.     // Find a substring
  3201.     //////////////////////////////////////////////////////////////////////////
  3202.     /*!
  3203.     \brief
  3204.         Search forwards for a sub-string
  3205.  
  3206.     \param str
  3207.         String object describing the sub-string to search for
  3208.  
  3209.     \param idx
  3210.         Index of the code point where the search is to start
  3211.  
  3212.     \return
  3213.         - Index of the first occurrence of sub-string \a str travelling forwards from \a idx.
  3214.         - npos if the sub-string could not be found
  3215.     */
  3216.     size_type    find(const String& str, size_type idx = 0) const
  3217.     {
  3218.         if ((str.d_cplength == 0) && (idx < d_cplength))
  3219.             return idx;
  3220.  
  3221.         if (idx < d_cplength)
  3222.         {
  3223.             // loop while search string could fit in to search area
  3224.             while (d_cplength - idx >= str.d_cplength)
  3225.             {
  3226.                 if (0 == compare(idx, str.d_cplength, str))
  3227.                     return idx;
  3228.  
  3229.                 ++idx;
  3230.             }
  3231.  
  3232.         }
  3233.  
  3234.         return npos;
  3235.     }
  3236.  
  3237.     /*!
  3238.     \brief
  3239.         Search backwards for a sub-string
  3240.  
  3241.     \param str
  3242.         String object describing the sub-string to search for
  3243.  
  3244.     \param idx
  3245.         Index of the code point where the search is to start
  3246.  
  3247.     \return
  3248.         - Index of the first occurrence of sub-string \a str travelling backwards from \a idx.
  3249.         - npos if the sub-string could not be found
  3250.     */
  3251.     size_type    rfind(const String& str, size_type idx = npos) const
  3252.     {
  3253.         if (str.d_cplength == 0)
  3254.             return (idx < d_cplength) ? idx : d_cplength;
  3255.  
  3256.         if (str.d_cplength <= d_cplength)
  3257.         {
  3258.             if (idx > (d_cplength - str.d_cplength))
  3259.                 idx = d_cplength - str.d_cplength;
  3260.  
  3261.             do
  3262.             {
  3263.                 if (0 == compare(idx, str.d_cplength, str))
  3264.                     return idx;
  3265.  
  3266.             } while (idx-- != 0);
  3267.  
  3268.         }
  3269.  
  3270.         return npos;
  3271.     }
  3272.  
  3273.     /*!
  3274.     \brief
  3275.         Search forwards for a sub-string
  3276.  
  3277.     \param std_str
  3278.         std::string object describing the sub-string to search for
  3279.  
  3280.     \note
  3281.         Characters from \a std_str are considered to represent Unicode code points in the range 0x00..0xFF.  No translation of
  3282.         the encountered data is performed.
  3283.  
  3284.     \param idx
  3285.         Index of the code point where the search is to start
  3286.  
  3287.     \return
  3288.         - Index of the first occurrence of sub-string \a std_str travelling forwards from \a idx.
  3289.         - npos if the sub-string could not be found
  3290.     */
  3291.     size_type    find(const std::string& std_str, size_type idx = 0) const
  3292.     {
  3293.         std::string::size_type sze = std_str.size();
  3294.  
  3295.         if ((sze == 0) && (idx < d_cplength))
  3296.             return idx;
  3297.  
  3298.         if (idx < d_cplength)
  3299.         {
  3300.             // loop while search string could fit in to search area
  3301.             while (d_cplength - idx >= sze)
  3302.             {
  3303.                 if (0 == compare(idx, (size_type)sze, std_str))
  3304.                     return idx;
  3305.  
  3306.                 ++idx;
  3307.             }
  3308.  
  3309.         }
  3310.  
  3311.         return npos;
  3312.     }
  3313.  
  3314.     /*!
  3315.     \brief
  3316.         Search backwards for a sub-string
  3317.  
  3318.     \param std_str
  3319.         std::string object describing the sub-string to search for
  3320.  
  3321.     \note
  3322.         Characters from \a std_str are considered to represent Unicode code points in the range 0x00..0xFF.  No translation of
  3323.         the encountered data is performed.
  3324.  
  3325.     \param idx
  3326.         Index of the code point where the search is to start
  3327.  
  3328.     \return
  3329.         - Index of the first occurrence of sub-string \a std_str travelling backwards from \a idx.
  3330.         - npos if the sub-string could not be found
  3331.     */
  3332.     size_type    rfind(const std::string& std_str, size_type idx = npos) const
  3333.     {
  3334.         std::string::size_type sze = std_str.size();
  3335.  
  3336.         if (sze == 0)
  3337.             return (idx < d_cplength) ? idx : d_cplength;
  3338.  
  3339.         if (sze <= d_cplength)
  3340.         {
  3341.             if (idx > (d_cplength - sze))
  3342.                 idx = d_cplength - sze;
  3343.  
  3344.             do
  3345.             {
  3346.                 if (0 == compare(idx, (size_type)sze, std_str))
  3347.                     return idx;
  3348.  
  3349.             } while (idx-- != 0);
  3350.  
  3351.         }
  3352.  
  3353.         return npos;
  3354.     }
  3355.  
  3356.     /*!
  3357.     \brief
  3358.         Search forwards for a sub-string
  3359.  
  3360.     \param utf8_str
  3361.         Buffer containing null-terminated utf8 encoded data describing the sub-string to search for
  3362.  
  3363.     \note
  3364.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  3365.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  3366.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  3367.         results.
  3368.  
  3369.     \param idx
  3370.         Index of the code point where the search is to start
  3371.  
  3372.     \return
  3373.         - Index of the first occurrence of sub-string \a utf8_str travelling forwards from \a idx.
  3374.         - npos if the sub-string could not be found
  3375.  
  3376.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  3377.     */
  3378.     size_type    find(const utf8* utf8_str, size_type idx = 0) const
  3379.     {
  3380.         return find(utf8_str, idx, utf_length(utf8_str));
  3381.     }
  3382.  
  3383.     /*!
  3384.     \brief
  3385.         Search backwards for a sub-string
  3386.  
  3387.     \param utf8_str
  3388.         Buffer containing null-terminated utf8 encoded data describing the sub-string to search for
  3389.  
  3390.     \note
  3391.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  3392.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  3393.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  3394.         results.
  3395.  
  3396.     \param idx
  3397.         Index of the code point where the search is to start
  3398.  
  3399.     \return
  3400.         - Index of the first occurrence of sub-string \a utf8_str travelling backwards from \a idx.
  3401.         - npos if the sub-string could not be found
  3402.  
  3403.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  3404.     */
  3405.     size_type    rfind(const utf8* utf8_str, size_type idx = npos) const
  3406.     {
  3407.         return rfind(utf8_str, idx, utf_length(utf8_str));
  3408.     }
  3409.  
  3410.     /*!
  3411.     \brief
  3412.         Search forwards for a sub-string
  3413.  
  3414.     \param utf8_str
  3415.         Buffer containing utf8 encoded data describing the sub-string to search for
  3416.  
  3417.     \note
  3418.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  3419.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  3420.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  3421.         results.
  3422.  
  3423.     \param idx
  3424.         Index of the code point where the search is to start
  3425.  
  3426.     \param str_len
  3427.         Length of the utf8 encoded sub-string in utf8 code units (not code points)
  3428.  
  3429.     \return
  3430.         - Index of the first occurrence of sub-string \a utf8_str travelling forwards from \a idx.
  3431.         - npos if the sub-string could not be found
  3432.  
  3433.     \exception std::length_error    Thrown if \a str_len is 'npos'
  3434.     */
  3435.     size_type    find(const utf8* utf8_str, size_type idx, size_type str_len) const
  3436.     {
  3437.         if (str_len == npos)
  3438.             throw std::length_error("Length for utf8 encoded string can not be 'npos'");
  3439.  
  3440.         size_type sze = encoded_size(utf8_str, str_len);
  3441.  
  3442.         if ((sze == 0) && (idx < d_cplength))
  3443.             return idx;
  3444.  
  3445.         if (idx < d_cplength)
  3446.         {
  3447.             // loop while search string could fit in to search area
  3448.             while (d_cplength - idx >= sze)
  3449.             {
  3450.                 if (0 == compare(idx, sze, utf8_str, sze))
  3451.                     return idx;
  3452.  
  3453.                 ++idx;
  3454.             }
  3455.  
  3456.         }
  3457.  
  3458.         return npos;
  3459.     }
  3460.  
  3461.     /*!
  3462.     \brief
  3463.         Search backwards for a sub-string
  3464.  
  3465.     \param utf8_str
  3466.         Buffer containing utf8 encoded data describing the sub-string to search for
  3467.  
  3468.     \note
  3469.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  3470.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  3471.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  3472.         results.
  3473.  
  3474.     \param idx
  3475.         Index of the code point where the search is to start
  3476.  
  3477.     \param str_len
  3478.         Length of the utf8 encoded sub-string in utf8 code units (not code points)
  3479.  
  3480.     \return
  3481.         - Index of the first occurrence of sub-string \a utf8_str travelling backwards from \a idx.
  3482.         - npos if the sub-string could not be found
  3483.  
  3484.     \exception std::length_error    Thrown if \a str_len is 'npos'
  3485.     */
  3486.     size_type    rfind(const utf8* utf8_str, size_type idx, size_type str_len) const
  3487.     {
  3488.         if (str_len == npos)
  3489.             throw std::length_error("Length for utf8 encoded string can not be 'npos'");
  3490.  
  3491.         size_type sze = encoded_size(utf8_str, str_len);
  3492.  
  3493.         if (sze == 0)
  3494.             return (idx < d_cplength) ? idx : d_cplength;
  3495.  
  3496.         if (sze <= d_cplength)
  3497.         {
  3498.             if (idx > (d_cplength - sze))
  3499.                 idx = d_cplength - sze;
  3500.  
  3501.             do
  3502.             {
  3503.                 if (0 == compare(idx, sze, utf8_str, sze))
  3504.                     return idx;
  3505.  
  3506.             } while (idx-- != 0);
  3507.  
  3508.         }
  3509.  
  3510.         return npos;
  3511.     }
  3512.  
  3513.  
  3514.     /*!
  3515.     \brief
  3516.         Search forwards for a sub-string
  3517.  
  3518.     \param c_str
  3519.         c-string describing the sub-string to search for
  3520.  
  3521.     \param idx
  3522.         Index of the code point where the search is to start
  3523.  
  3524.     \return
  3525.         - Index of the first occurrence of sub-string \a c_str travelling forwards from \a idx.
  3526.         - npos if the sub-string could not be found
  3527.  
  3528.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  3529.     */
  3530.     size_type    find(const char* cstr, size_type idx = 0) const
  3531.     {
  3532.         return find(cstr, idx, strlen(cstr));
  3533.     }
  3534.  
  3535.  
  3536.     /*!
  3537.     \brief
  3538.         Search backwards for a sub-string
  3539.  
  3540.     \param c_str
  3541.         c-string describing the sub-string to search for
  3542.  
  3543.     \param idx
  3544.         Index of the code point where the search is to start
  3545.  
  3546.     \return
  3547.         - Index of the first occurrence of sub-string \a c_str travelling backwards from \a idx.
  3548.         - npos if the sub-string could not be found
  3549.  
  3550.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  3551.     */
  3552.     size_type    rfind(const char* cstr, size_type idx = npos) const
  3553.     {
  3554.         return rfind(cstr, idx, strlen(cstr));
  3555.     }
  3556.  
  3557.  
  3558.     /*!
  3559.     \brief
  3560.         Search forwards for a sub-string
  3561.  
  3562.     \param chars
  3563.         char array describing the sub-string to search for
  3564.  
  3565.     \param idx
  3566.         Index of the code point where the search is to start
  3567.  
  3568.     \param chars_len
  3569.         Number of chars in the char array.
  3570.  
  3571.     \return
  3572.         - Index of the first occurrence of sub-string \a chars travelling forwards from \a idx.
  3573.         - npos if the sub-string could not be found
  3574.  
  3575.     \exception std::length_error    Thrown if \a chars_len is 'npos'
  3576.     */
  3577.     size_type    find(const char* chars, size_type idx, size_type chars_len) const
  3578.     {
  3579.         if (chars_len == npos)
  3580.             throw std::length_error("Length for char array can not be 'npos'");
  3581.  
  3582.         if ((chars_len == 0) && (idx < d_cplength))
  3583.             return idx;
  3584.  
  3585.         if (idx < d_cplength)
  3586.         {
  3587.             // loop while search string could fit in to search area
  3588.             while (d_cplength - idx >= chars_len)
  3589.             {
  3590.                 if (0 == compare(idx, chars_len, chars, chars_len))
  3591.                     return idx;
  3592.  
  3593.                 ++idx;
  3594.             }
  3595.  
  3596.         }
  3597.  
  3598.         return npos;
  3599.     }
  3600.  
  3601.  
  3602.     /*!
  3603.     \brief
  3604.         Search backwards for a sub-string
  3605.  
  3606.     \param chars
  3607.         char array describing the sub-string to search for
  3608.  
  3609.     \param idx
  3610.         Index of the code point where the search is to start
  3611.  
  3612.     \param chars_len
  3613.         Number of chars in the char array.
  3614.  
  3615.     \return
  3616.         - Index of the first occurrence of sub-string \a chars travelling backwards from \a idx.
  3617.         - npos if the sub-string could not be found
  3618.  
  3619.     \exception std::length_error    Thrown if \a chars_len is 'npos'
  3620.     */
  3621.     size_type    rfind(const char* chars, size_type idx, size_type chars_len) const
  3622.     {
  3623.         if (chars_len == npos)
  3624.             throw std::length_error("Length for char array can not be 'npos'");
  3625.  
  3626.         if (chars_len == 0)
  3627.             return (idx < d_cplength) ? idx : d_cplength;
  3628.  
  3629.         if (chars_len <= d_cplength)
  3630.         {
  3631.             if (idx > (d_cplength - chars_len))
  3632.                 idx = d_cplength - chars_len;
  3633.  
  3634.             do
  3635.             {
  3636.                 if (0 == compare(idx, chars_len, chars, chars_len))
  3637.                     return idx;
  3638.  
  3639.             } while (idx-- != 0);
  3640.  
  3641.         }
  3642.  
  3643.         return npos;
  3644.     }
  3645.  
  3646.  
  3647.     //////////////////////////////////////////////////////////////////////////
  3648.     // Find first of different code-points
  3649.     //////////////////////////////////////////////////////////////////////////
  3650.     /*!
  3651.     \brief
  3652.         Find the first occurrence of one of a set of code points.
  3653.  
  3654.     \param str
  3655.         String object describing the set of code points.
  3656.  
  3657.     \param idx
  3658.         Index of the start point for the search
  3659.  
  3660.     \return
  3661.         - Index of the first occurrence of any one of the code points in \a str starting from from \a idx.
  3662.         - npos if none of the code points in \a str were found.
  3663.     */
  3664.     size_type    find_first_of(const String& str, size_type idx = 0) const
  3665.     {
  3666.         if (idx < d_cplength)
  3667.         {
  3668.             const utf32* pt = &ptr()[idx];
  3669.  
  3670.             do
  3671.             {
  3672.                 if (npos != str.find(*pt++))
  3673.                     return idx;
  3674.  
  3675.             } while (++idx != d_cplength);
  3676.  
  3677.         }
  3678.  
  3679.         return npos;
  3680.     }
  3681.  
  3682.     /*!
  3683.     \brief
  3684.         Find the first code point that is not one of a set of code points.
  3685.  
  3686.     \param str
  3687.         String object describing the set of code points.
  3688.  
  3689.     \param idx
  3690.         Index of the start point for the search
  3691.  
  3692.     \return
  3693.         - Index of the first code point that does not match any one of the code points in \a str starting from from \a idx.
  3694.         - npos if all code points matched one of the code points in \a str.
  3695.     */
  3696.     size_type    find_first_not_of(const String& str, size_type idx = 0) const
  3697.     {
  3698.         if (idx < d_cplength)
  3699.         {
  3700.             const utf32* pt = &ptr()[idx];
  3701.  
  3702.             do
  3703.             {
  3704.                 if (npos == str.find(*pt++))
  3705.                     return idx;
  3706.  
  3707.             } while (++idx != d_cplength);
  3708.  
  3709.         }
  3710.  
  3711.         return npos;
  3712.     }
  3713.  
  3714.  
  3715.     /*!
  3716.     \brief
  3717.         Find the first occurrence of one of a set of code points.
  3718.  
  3719.     \param std_str
  3720.         std::string object describing the set of code points.
  3721.  
  3722.     \note
  3723.         The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
  3724.         the provided data will occur.
  3725.  
  3726.     \param idx
  3727.         Index of the start point for the search
  3728.  
  3729.     \return
  3730.         - Index of the first occurrence of any one of the code points in \a std_str starting from from \a idx.
  3731.         - npos if none of the code points in \a std_str were found.
  3732.     */
  3733.     size_type    find_first_of(const std::string& std_str, size_type idx = 0) const
  3734.     {
  3735.         if (idx < d_cplength)
  3736.         {
  3737.             const utf32* pt = &ptr()[idx];
  3738.  
  3739.             do
  3740.             {
  3741.                 if (npos != find_codepoint(std_str, *pt++))
  3742.                     return idx;
  3743.  
  3744.             } while (++idx != d_cplength);
  3745.  
  3746.         }
  3747.  
  3748.         return npos;
  3749.     }
  3750.  
  3751.     /*!
  3752.     \brief
  3753.         Find the first code point that is not one of a set of code points.
  3754.  
  3755.     \param std_str
  3756.         std::string object describing the set of code points.
  3757.  
  3758.     \note
  3759.         The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
  3760.         the provided data will occur.
  3761.  
  3762.     \param idx
  3763.         Index of the start point for the search
  3764.  
  3765.     \return
  3766.         - Index of the first code point that does not match any one of the code points in \a std_str starting from from \a idx.
  3767.         - npos if all code points matched one of the code points in \a std_str.
  3768.     */
  3769.     size_type    find_first_not_of(const std::string& std_str, size_type idx = 0) const
  3770.     {
  3771.         if (idx < d_cplength)
  3772.         {
  3773.             const utf32* pt = &ptr()[idx];
  3774.  
  3775.             do
  3776.             {
  3777.                 if (npos == find_codepoint(std_str, *pt++))
  3778.                     return idx;
  3779.  
  3780.             } while (++idx != d_cplength);
  3781.  
  3782.         }
  3783.  
  3784.         return npos;
  3785.     }
  3786.  
  3787.  
  3788.     /*!
  3789.     \brief
  3790.         Find the first occurrence of one of a set of code points.
  3791.  
  3792.     \param utf8_str
  3793.         Buffer containing null-terminated utf8 encoded data describing the set of code points.
  3794.  
  3795.     \note
  3796.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  3797.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  3798.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  3799.         results.
  3800.  
  3801.     \param idx
  3802.         Index of the start point for the search
  3803.  
  3804.     \return
  3805.         - Index of the first occurrence of any one of the code points in \a utf8_str starting from from \a idx.
  3806.         - npos if none of the code points in \a utf8_str were found.
  3807.  
  3808.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  3809.     */
  3810.     size_type    find_first_of(const utf8* utf8_str, size_type idx = 0) const
  3811.     {
  3812.         return find_first_of(utf8_str, idx, utf_length(utf8_str));
  3813.     }
  3814.  
  3815.     /*!
  3816.     \brief
  3817.         Find the first code point that is not one of a set of code points.
  3818.  
  3819.     \param utf8_str
  3820.         Buffer containing null-terminated utf8 encoded data describing the set of code points.
  3821.  
  3822.     \note
  3823.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  3824.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  3825.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  3826.         results.
  3827.  
  3828.     \param idx
  3829.         Index of the start point for the search
  3830.  
  3831.     \return
  3832.         - Index of the first code point that does not match any one of the code points in \a utf8_str starting from from \a idx.
  3833.         - npos if all code points matched one of the code points in \a utf8_str.
  3834.  
  3835.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  3836.     */
  3837.     size_type    find_first_not_of(const utf8* utf8_str, size_type idx = 0) const
  3838.     {
  3839.         return find_first_not_of(utf8_str, idx, utf_length(utf8_str));
  3840.     }
  3841.  
  3842.     /*!
  3843.     \brief
  3844.         Find the first occurrence of one of a set of code points.
  3845.  
  3846.     \param utf8_str
  3847.         Buffer containing utf8 encoded data describing the set of code points.
  3848.  
  3849.     \note
  3850.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  3851.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  3852.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  3853.         results.
  3854.  
  3855.     \param idx
  3856.         Index of the start point for the search
  3857.  
  3858.     \param str_len
  3859.         Length of the utf8 encoded data in utf8 code units (not code points).
  3860.  
  3861.     \return
  3862.         - Index of the first occurrence of any one of the code points in \a utf8_str starting from from \a idx.
  3863.         - npos if none of the code points in \a utf8_str were found.
  3864.  
  3865.     \exception std::length_error    Thrown if \a str_len was 'npos'.
  3866.     */
  3867.     size_type    find_first_of(const utf8* utf8_str, size_type idx, size_type str_len) const
  3868.     {
  3869.         if (str_len == npos)
  3870.             throw std::length_error("Length for utf8 encoded string can not be 'npos'");
  3871.  
  3872.         if (idx < d_cplength)
  3873.         {
  3874.             size_type encsze = encoded_size(utf8_str, str_len);
  3875.  
  3876.             const utf32* pt = &ptr()[idx];
  3877.  
  3878.             do
  3879.             {
  3880.                 if (npos != find_codepoint(utf8_str, encsze, *pt++))
  3881.                     return idx;
  3882.  
  3883.             } while (++idx != d_cplength);
  3884.  
  3885.         }
  3886.  
  3887.         return npos;
  3888.     }
  3889.  
  3890.     /*!
  3891.     \brief
  3892.         Find the first code point that is not one of a set of code points.
  3893.  
  3894.     \param utf8_str
  3895.         Buffer containing utf8 encoded data describing the set of code points.
  3896.  
  3897.     \note
  3898.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  3899.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  3900.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  3901.         results.
  3902.  
  3903.     \param idx
  3904.         Index of the start point for the search
  3905.  
  3906.     \param str_len
  3907.         Length of the utf8 encoded data in utf8 code units (not code points).
  3908.  
  3909.     \return
  3910.         - Index of the first code point that does not match any one of the code points in \a utf8_str starting from from \a idx.
  3911.         - npos if all code points matched one of the code points in \a utf8_str.
  3912.  
  3913.     \exception std::length_error    Thrown if \a str_len was 'npos'.
  3914.     */
  3915.     size_type    find_first_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
  3916.     {
  3917.         if (str_len == npos)
  3918.             throw std::length_error("Length for utf8 encoded string can not be 'npos'");
  3919.  
  3920.         if (idx < d_cplength)
  3921.         {
  3922.             size_type encsze = encoded_size(utf8_str, str_len);
  3923.  
  3924.             const utf32* pt = &ptr()[idx];
  3925.  
  3926.             do
  3927.             {
  3928.                 if (npos == find_codepoint(utf8_str, encsze, *pt++))
  3929.                     return idx;
  3930.  
  3931.             } while (++idx != d_cplength);
  3932.  
  3933.         }
  3934.  
  3935.         return npos;
  3936.     }
  3937.  
  3938.  
  3939.     /*!
  3940.     \brief
  3941.         Search forwards for a given code point
  3942.  
  3943.     \param code_point
  3944.         The utf32 code point to search for
  3945.  
  3946.     \param idx
  3947.         Index of the code point where the search is to start.
  3948.  
  3949.     \return
  3950.         - Index of the first occurrence of \a code_point starting from from \a idx.
  3951.         - npos if the code point could not be found
  3952.     */
  3953.     size_type    find_first_of(utf32 code_point, size_type idx = 0) const
  3954.     {
  3955.         return find(code_point, idx);
  3956.     }
  3957.  
  3958.     /*!
  3959.     \brief
  3960.         Search forwards for the first code point that does not match a given code point
  3961.  
  3962.     \param code_point
  3963.         The utf32 code point to search for
  3964.  
  3965.     \param idx
  3966.         Index of the code point where the search is to start.
  3967.  
  3968.     \return
  3969.         - Index of the first code point that does not match \a code_point starting from from \a idx.
  3970.         - npos if all code points matched \a code_point
  3971.  
  3972.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  3973.     */
  3974.     size_type    find_first_not_of(utf32 code_point, size_type idx = 0) const
  3975.     {
  3976.         if (idx < d_cplength)
  3977.         {
  3978.             do
  3979.             {
  3980.                 if ((*this)[idx] != code_point)
  3981.                     return idx;
  3982.  
  3983.             } while(idx++ < d_cplength);
  3984.  
  3985.         }
  3986.  
  3987.         return npos;
  3988.     }
  3989.  
  3990.  
  3991.     /*!
  3992.     \brief
  3993.         Find the first occurrence of one of a set of chars.
  3994.  
  3995.     \param c_str
  3996.         c-string describing the set of chars.
  3997.  
  3998.     \param idx
  3999.         Index of the start point for the search
  4000.  
  4001.     \return
  4002.         - Index of the first occurrence of any one of the chars in \a c_str starting from from \a idx.
  4003.         - npos if none of the chars in \a c_str were found.
  4004.  
  4005.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  4006.     */
  4007.     size_type    find_first_of(const char* cstr, size_type idx = 0) const
  4008.     {
  4009.         return find_first_of(cstr, idx, strlen(cstr));
  4010.     }
  4011.  
  4012.  
  4013.     /*!
  4014.     \brief
  4015.         Find the first code point that is not one of a set of chars.
  4016.  
  4017.     \param c_str
  4018.         c-string describing the set of chars.
  4019.  
  4020.     \param idx
  4021.         Index of the start point for the search
  4022.  
  4023.     \return
  4024.         - Index of the first code point that does not match any one of the chars in \a c_str starting from from \a idx.
  4025.         - npos if all code points matched any of the chars in \a c_str.
  4026.  
  4027.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  4028.     */
  4029.     size_type    find_first_not_of(const char* cstr, size_type idx = 0) const
  4030.     {
  4031.         return find_first_not_of(cstr, idx, strlen(cstr));
  4032.     }
  4033.  
  4034.  
  4035.     /*!
  4036.     \brief
  4037.         Find the first occurrence of one of a set of chars.
  4038.  
  4039.     \param chars
  4040.         char array containing the set of chars.
  4041.  
  4042.     \param idx
  4043.         Index of the start point for the search
  4044.  
  4045.     \param chars_len
  4046.         Number of chars in the char array.
  4047.  
  4048.     \return
  4049.         - Index of the first occurrence of any one of the chars in \a chars starting from from \a idx.
  4050.         - npos if none of the chars in \a chars were found.
  4051.  
  4052.     \exception std::length_error    Thrown if \a chars_len was 'npos'.
  4053.     */
  4054.     size_type    find_first_of(const char* chars, size_type idx, size_type chars_len) const
  4055.     {
  4056.         if (chars_len == npos)
  4057.             throw std::length_error("Length for char array can not be 'npos'");
  4058.  
  4059.         if (idx < d_cplength)
  4060.         {
  4061.             const utf32* pt = &ptr()[idx];
  4062.  
  4063.             do
  4064.             {
  4065.                 if (npos != find_codepoint(chars, chars_len, *pt++))
  4066.                     return idx;
  4067.  
  4068.             } while (++idx != d_cplength);
  4069.  
  4070.         }
  4071.  
  4072.         return npos;
  4073.     }
  4074.  
  4075.  
  4076.     /*!
  4077.     \brief
  4078.         Find the first code point that is not one of a set of chars.
  4079.  
  4080.     \param chars
  4081.         char array containing the set of chars.
  4082.  
  4083.     \param idx
  4084.         Index of the start point for the search
  4085.  
  4086.     \param chars_len
  4087.         Number of chars in the car array.
  4088.  
  4089.     \return
  4090.         - Index of the first code point that does not match any one of the chars in \a chars starting from from \a idx.
  4091.         - npos if all code points matched any of the chars in \a chars.
  4092.  
  4093.     \exception std::length_error    Thrown if \a chars_len was 'npos'.
  4094.     */
  4095.     size_type    find_first_not_of(const char* chars, size_type idx, size_type chars_len) const
  4096.     {
  4097.         if (chars_len == npos)
  4098.             throw std::length_error("Length for char array can not be 'npos'");
  4099.  
  4100.         if (idx < d_cplength)
  4101.         {
  4102.             const utf32* pt = &ptr()[idx];
  4103.  
  4104.             do
  4105.             {
  4106.                 if (npos == find_codepoint(chars, chars_len, *pt++))
  4107.                     return idx;
  4108.  
  4109.             } while (++idx != d_cplength);
  4110.  
  4111.         }
  4112.  
  4113.         return npos;
  4114.     }
  4115.  
  4116.  
  4117.     //////////////////////////////////////////////////////////////////////////
  4118.     // Find last of different code-points
  4119.     //////////////////////////////////////////////////////////////////////////
  4120.     /*!
  4121.     \brief
  4122.         Find the last occurrence of one of a set of code points.
  4123.  
  4124.     \param str
  4125.         String object describing the set of code points.
  4126.  
  4127.     \param idx
  4128.         Index of the start point for the search
  4129.  
  4130.     \return
  4131.         - Index of the last occurrence of any one of the code points in \a str starting from \a idx.
  4132.         - npos if none of the code points in \a str were found.
  4133.     */
  4134.     size_type    find_last_of(const String& str, size_type idx = npos) const
  4135.     {
  4136.         if (d_cplength > 0)
  4137.         {
  4138.             if (idx >= d_cplength)
  4139.                 idx = d_cplength - 1;
  4140.  
  4141.             const utf32* pt = &ptr()[idx];
  4142.  
  4143.             do
  4144.             {
  4145.                 if (npos != str.find(*pt--))
  4146.                     return idx;
  4147.  
  4148.             } while (idx-- != 0);
  4149.  
  4150.         }
  4151.  
  4152.         return npos;
  4153.     }
  4154.  
  4155.     /*!
  4156.     \brief
  4157.         Find the last code point that is not one of a set of code points.
  4158.  
  4159.     \param str
  4160.         String object describing the set of code points.
  4161.  
  4162.     \param idx
  4163.         Index of the start point for the search
  4164.  
  4165.     \return
  4166.         - Index of the last code point that does not match any one of the code points in \a str starting from \a idx.
  4167.         - npos if all code points matched one of the code points in \a str.
  4168.     */
  4169.     size_type    find_last_not_of(const String& str, size_type idx = npos) const
  4170.     {
  4171.         if (d_cplength > 0)
  4172.         {
  4173.             if (idx >= d_cplength)
  4174.                 idx = d_cplength - 1;
  4175.  
  4176.             const utf32* pt = &ptr()[idx];
  4177.  
  4178.             do
  4179.             {
  4180.                 if (npos == str.find(*pt--))
  4181.                     return idx;
  4182.  
  4183.             } while (idx-- != 0);
  4184.  
  4185.         }
  4186.  
  4187.         return npos;
  4188.     }
  4189.  
  4190.  
  4191.     /*!
  4192.     \brief
  4193.         Find the last occurrence of one of a set of code points.
  4194.  
  4195.     \param std_str
  4196.         std::string object describing the set of code points.
  4197.  
  4198.     \note
  4199.         The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
  4200.         the provided data will occur.
  4201.  
  4202.     \param idx
  4203.         Index of the start point for the search
  4204.  
  4205.     \return
  4206.         - Index of the last occurrence of any one of the code points in \a std_str starting from \a idx.
  4207.         - npos if none of the code points in \a std_str were found.
  4208.     */
  4209.     size_type    find_last_of(const std::string& std_str, size_type idx = npos) const
  4210.     {
  4211.         if (d_cplength > 0)
  4212.         {
  4213.             if (idx >= d_cplength)
  4214.                 idx = d_cplength - 1;
  4215.  
  4216.             const utf32* pt = &ptr()[idx];
  4217.  
  4218.             do
  4219.             {
  4220.                 if (npos != find_codepoint(std_str, *pt--))
  4221.                     return idx;
  4222.  
  4223.             } while (idx-- != 0);
  4224.  
  4225.         }
  4226.  
  4227.         return npos;
  4228.     }
  4229.  
  4230.     /*!
  4231.     \brief
  4232.         Find the last code point that is not one of a set of code points.
  4233.  
  4234.     \param std_str
  4235.         std::string object describing the set of code points.
  4236.  
  4237.     \note
  4238.         The characters of \a std_str are taken to be unencoded data which represent Unicode code points 0x00..0xFF.  No translation of
  4239.         the provided data will occur.
  4240.  
  4241.     \param idx
  4242.         Index of the start point for the search
  4243.  
  4244.     \return
  4245.         - Index of the last code point that does not match any one of the code points in \a std_str starting from \a idx.
  4246.         - npos if all code points matched one of the code points in \a std_str.
  4247.     */
  4248.     size_type    find_last_not_of(const std::string& std_str, size_type idx = npos) const
  4249.     {
  4250.         if (d_cplength > 0)
  4251.         {
  4252.             if (idx >= d_cplength)
  4253.                 idx = d_cplength - 1;
  4254.  
  4255.             const utf32* pt = &ptr()[idx];
  4256.  
  4257.             do
  4258.             {
  4259.                 if (npos == find_codepoint(std_str, *pt--))
  4260.                     return idx;
  4261.  
  4262.             } while (idx-- != 0);
  4263.  
  4264.         }
  4265.  
  4266.         return npos;
  4267.     }
  4268.  
  4269.  
  4270.     /*!
  4271.     \brief
  4272.         Find the last occurrence of one of a set of code points.
  4273.  
  4274.     \param utf8_str
  4275.         Buffer containing null-terminated utf8 encoded data describing the set of code points.
  4276.  
  4277.     \note
  4278.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  4279.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  4280.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  4281.         results.
  4282.  
  4283.     \param idx
  4284.         Index of the start point for the search
  4285.  
  4286.     \return
  4287.         - Index of the last occurrence of any one of the code points in \a utf8_str starting from \a idx.
  4288.         - npos if none of the code points in \a utf8_str were found.
  4289.  
  4290.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  4291.     */
  4292.     size_type    find_last_of(const utf8* utf8_str, size_type idx = npos) const
  4293.     {
  4294.         return find_last_of(utf8_str, idx, utf_length(utf8_str));
  4295.     }
  4296.  
  4297.     /*!
  4298.     \brief
  4299.         Find the last code point that is not one of a set of code points.
  4300.  
  4301.     \param utf8_str
  4302.         Buffer containing null-terminated utf8 encoded data describing the set of code points.
  4303.  
  4304.     \note
  4305.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  4306.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  4307.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  4308.         results.
  4309.  
  4310.     \param idx
  4311.         Index of the start point for the search
  4312.  
  4313.     \return
  4314.         - Index of the last code point that does not match any one of the code points in \a utf8_str starting from \a idx.
  4315.         - npos if all code points matched one of the code points in \a utf8_str.
  4316.  
  4317.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  4318.     */
  4319.     size_type    find_last_not_of(const utf8* utf8_str, size_type idx = npos) const
  4320.     {
  4321.         return find_last_not_of(utf8_str, idx, utf_length(utf8_str));
  4322.     }
  4323.  
  4324.     /*!
  4325.     \brief
  4326.         Find the last occurrence of one of a set of code points.
  4327.  
  4328.     \param utf8_str
  4329.         Buffer containing utf8 encoded data describing the set of code points.
  4330.  
  4331.     \note
  4332.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  4333.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  4334.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  4335.         results.
  4336.  
  4337.     \param idx
  4338.         Index of the start point for the search
  4339.  
  4340.     \param str_len
  4341.         Length of the utf8 encoded data in utf8 code units (not code points).
  4342.  
  4343.     \return
  4344.         - Index of the last occurrence of any one of the code points in \a utf8_str starting from from \a idx.
  4345.         - npos if none of the code points in \a utf8_str were found.
  4346.  
  4347.     \exception std::length_error    Thrown if \a str_len was 'npos'.
  4348.     */
  4349.     size_type    find_last_of(const utf8* utf8_str, size_type idx, size_type str_len) const
  4350.     {
  4351.         if (str_len == npos)
  4352.             throw std::length_error("Length for utf8 encoded string can not be 'npos'");
  4353.  
  4354.         if (d_cplength > 0)
  4355.         {
  4356.             if (idx >= d_cplength)
  4357.                 idx = d_cplength - 1;
  4358.  
  4359.             size_type encsze = encoded_size(utf8_str, str_len);
  4360.  
  4361.             const utf32* pt = &ptr()[idx];
  4362.  
  4363.             do
  4364.             {
  4365.                 if (npos != find_codepoint(utf8_str, encsze, *pt--))
  4366.                     return idx;
  4367.  
  4368.             } while (idx-- != 0);
  4369.  
  4370.         }
  4371.  
  4372.         return npos;
  4373.     }
  4374.  
  4375.     /*!
  4376.     \brief
  4377.         Find the last code point that is not one of a set of code points.
  4378.  
  4379.     \param utf8_str
  4380.         Buffer containing utf8 encoded data describing the set of code points.
  4381.  
  4382.     \note
  4383.         A basic string literal (cast to utf8*) can be passed to this function, provided that the string is
  4384.         comprised only of code points 0x00..0x7f.  The use of extended ASCII characters (with values >0x7f)
  4385.         would result in incorrect behaviour as the String will attempt to 'decode' the data, with unpredictable
  4386.         results.
  4387.  
  4388.     \param idx
  4389.         Index of the start point for the search
  4390.  
  4391.     \param str_len
  4392.         Length of the utf8 encoded data in utf8 code units (not code points).
  4393.  
  4394.     \return
  4395.         - Index of the last code point that does not match any one of the code points in \a utf8_str starting from from \a idx.
  4396.         - npos if all code points matched one of the code points in \a utf8_str.
  4397.  
  4398.     \exception std::length_error    Thrown if \a str_len was 'npos'.
  4399.     */
  4400.     size_type    find_last_not_of(const utf8* utf8_str, size_type idx, size_type str_len) const
  4401.     {
  4402.         if (str_len == npos)
  4403.             throw std::length_error("Length for utf8 encoded string can not be 'npos'");
  4404.  
  4405.         if (d_cplength > 0)
  4406.         {
  4407.             if (idx >= d_cplength)
  4408.                 idx = d_cplength - 1;
  4409.  
  4410.             size_type encsze = encoded_size(utf8_str, str_len);
  4411.  
  4412.             const utf32* pt = &ptr()[idx];
  4413.  
  4414.             do
  4415.             {
  4416.                 if (npos == find_codepoint(utf8_str, encsze, *pt--))
  4417.                     return idx;
  4418.  
  4419.             } while (idx-- != 0);
  4420.  
  4421.         }
  4422.  
  4423.         return npos;
  4424.     }
  4425.  
  4426.  
  4427.     /*!
  4428.     \brief
  4429.         Search for last occurrence of a given code point
  4430.  
  4431.     \param code_point
  4432.         The utf32 code point to search for
  4433.  
  4434.     \param idx
  4435.         Index of the code point where the search is to start.
  4436.  
  4437.     \return
  4438.         - Index of the last occurrence of \a code_point starting from \a idx.
  4439.         - npos if the code point could not be found
  4440.     */
  4441.     size_type    find_last_of(utf32 code_point, size_type idx = npos) const
  4442.     {
  4443.         return rfind(code_point, idx);
  4444.     }
  4445.  
  4446.     /*!
  4447.     \brief
  4448.         Search for the last code point that does not match a given code point
  4449.  
  4450.     \param code_point
  4451.         The utf32 code point to search for
  4452.  
  4453.     \param idx
  4454.         Index of the code point where the search is to start.
  4455.  
  4456.     \return
  4457.         - Index of the last code point that does not match \a code_point starting from from \a idx.
  4458.         - npos if all code points matched \a code_point
  4459.     */
  4460.     size_type    find_last_not_of(utf32 code_point, size_type idx = npos) const
  4461.     {
  4462.         if (d_cplength > 0)
  4463.         {
  4464.             if (idx >= d_cplength)
  4465.                 idx = d_cplength - 1;
  4466.  
  4467.             do
  4468.             {
  4469.                 if ((*this)[idx] != code_point)
  4470.                     return idx;
  4471.  
  4472.             } while(idx-- != 0);
  4473.  
  4474.         }
  4475.  
  4476.         return npos;
  4477.     }
  4478.  
  4479.  
  4480.     /*!
  4481.     \brief
  4482.         Find the last occurrence of one of a set of chars.
  4483.  
  4484.     \param c_str
  4485.         c-string describing the set of chars.
  4486.  
  4487.     \param idx
  4488.         Index of the start point for the search
  4489.  
  4490.     \return
  4491.         - Index of the last occurrence of any one of the chars in \a c_str starting from \a idx.
  4492.         - npos if none of the chars in \a c_str were found.
  4493.  
  4494.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  4495.     */
  4496.     size_type    find_last_of(const char* cstr, size_type idx = npos) const
  4497.     {
  4498.         return find_last_of(cstr, idx, strlen(cstr));
  4499.     }
  4500.  
  4501.  
  4502.     /*!
  4503.     \brief
  4504.         Find the last code point that is not one of a set of chars.
  4505.  
  4506.     \param c_str
  4507.         c-string describing the set of chars.
  4508.  
  4509.     \param idx
  4510.         Index of the start point for the search
  4511.  
  4512.     \return
  4513.         - Index of the last code point that does not match any one of the chars in \a c_str starting from \a idx.
  4514.         - npos if all code points matched any of the chars in \a c_str.
  4515.  
  4516.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  4517.     */
  4518.     size_type    find_last_not_of(const char* cstr, size_type idx = npos) const
  4519.     {
  4520.         return find_last_not_of(cstr, idx, strlen(cstr));
  4521.     }
  4522.  
  4523.  
  4524.     /*!
  4525.     \brief
  4526.         Find the last occurrence of one of a set of chars.
  4527.  
  4528.     \param chars
  4529.         char array containing the set of chars.
  4530.  
  4531.     \param idx
  4532.         Index of the start point for the search
  4533.  
  4534.     \param chars_len
  4535.         Number of chars in the char array.
  4536.  
  4537.     \return
  4538.         - Index of the last occurrence of any one of the chars in \a chars, starting from from \a idx.
  4539.         - npos if none of the chars in \a chars were found.
  4540.  
  4541.     \exception std::length_error    Thrown if \a chars_len was 'npos'.
  4542.     */
  4543.     size_type    find_last_of(const char* chars, size_type idx, size_type chars_len) const
  4544.     {
  4545.         if (chars_len == npos)
  4546.             throw std::length_error("Length for char array can not be 'npos'");
  4547.  
  4548.         if (d_cplength > 0)
  4549.         {
  4550.             if (idx >= d_cplength)
  4551.                 idx = d_cplength - 1;
  4552.  
  4553.             const utf32* pt = &ptr()[idx];
  4554.  
  4555.             do
  4556.             {
  4557.                 if (npos != find_codepoint(chars, chars_len, *pt--))
  4558.                     return idx;
  4559.  
  4560.             } while (idx-- != 0);
  4561.  
  4562.         }
  4563.  
  4564.         return npos;
  4565.     }
  4566.  
  4567.  
  4568.     /*!
  4569.     \brief
  4570.         Find the last code point that is not one of a set of chars.
  4571.  
  4572.     \param chars
  4573.         char array containing the set of chars.
  4574.  
  4575.     \param idx
  4576.         Index of the start point for the search
  4577.  
  4578.     \param chars_len
  4579.         Number of chars in the char array.
  4580.  
  4581.     \return
  4582.         - Index of the last code point that does not match any one of the chars in \a chars, starting from from \a idx.
  4583.         - npos if all code points matched any of the chars in \a chars.
  4584.  
  4585.     \exception std::length_error    Thrown if \a chars_len was 'npos'.
  4586.     */
  4587.     size_type    find_last_not_of(const char* chars, size_type idx, size_type chars_len) const
  4588.     {
  4589.         if (chars_len == npos)
  4590.             throw std::length_error("Length for char array can not be 'npos'");
  4591.  
  4592.         if (d_cplength > 0)
  4593.         {
  4594.             if (idx >= d_cplength)
  4595.                 idx = d_cplength - 1;
  4596.  
  4597.             const utf32* pt = &ptr()[idx];
  4598.  
  4599.             do
  4600.             {
  4601.                 if (npos == find_codepoint(chars, chars_len, *pt--))
  4602.                     return idx;
  4603.  
  4604.             } while (idx-- != 0);
  4605.  
  4606.         }
  4607.  
  4608.         return npos;
  4609.     }
  4610.  
  4611.  
  4612.     //////////////////////////////////////////////////////////////////////////
  4613.     // Substring
  4614.     //////////////////////////////////////////////////////////////////////////
  4615.     /*!
  4616.     \brief
  4617.         Returns a substring of this String.
  4618.  
  4619.     \param idx
  4620.         Index of the first code point to use for the sub-string.
  4621.  
  4622.     \param len
  4623.         Maximum number of code points to use for the sub-string
  4624.  
  4625.     \return
  4626.         A String object containing the specified sub-string.
  4627.  
  4628.     \exception std::out_of_range    Thrown if \a idx is invalid for this String.
  4629.     */
  4630.     String    substr(size_type idx = 0, size_type len = npos) const
  4631.     {
  4632.         if (d_cplength < idx)
  4633.             throw std::out_of_range("Index is out of range for this CEGUI::String");
  4634.  
  4635.         return String(*this, idx, len);
  4636.     }
  4637.  
  4638.     //////////////////////////////////////////////////////////////////////////
  4639.     // Iterator creation
  4640.     //////////////////////////////////////////////////////////////////////////
  4641.     /*!
  4642.     \brief
  4643.         Return a forwards iterator that describes the beginning of the String
  4644.  
  4645.     \return
  4646.         iterator object that describes the beginning of the String.
  4647.     */
  4648.     iterator        begin(void)
  4649.     {
  4650.         return iterator(ptr());
  4651.     }
  4652.  
  4653.     /*!
  4654.     \brief
  4655.         Return a constant forwards iterator that describes the beginning of the String
  4656.  
  4657.     \return
  4658.         const_iterator object that describes the beginning of the String.
  4659.     */
  4660.     const_iterator    begin(void) const
  4661.     {
  4662.         return const_iterator(ptr());
  4663.     }
  4664.  
  4665.     /*!
  4666.     \brief
  4667.         Return a forwards iterator that describes the end of the String
  4668.  
  4669.     \return
  4670.         iterator object that describes the end of the String.
  4671.     */
  4672.     iterator        end(void)
  4673.     {
  4674.         return iterator(&ptr()[d_cplength]);
  4675.     }
  4676.  
  4677.     /*!
  4678.     \brief
  4679.         Return a constant forwards iterator that describes the end of the String
  4680.  
  4681.     \return
  4682.         const_iterator object that describes the end of the String.
  4683.     */
  4684.     const_iterator    end(void) const
  4685.     {
  4686.         return const_iterator(&ptr()[d_cplength]);
  4687.     }
  4688.  
  4689.     /*!
  4690.     \brief
  4691.         Return a reverse iterator that describes the beginning of the String
  4692.  
  4693.     \return
  4694.         reverse_iterator object that describes the beginning of the String (so is actually at the end)
  4695.     */
  4696.     reverse_iterator        rbegin(void)
  4697.     {
  4698.         return reverse_iterator(end());
  4699.     }
  4700.  
  4701.     /*!
  4702.     \brief
  4703.         Return a constant reverse iterator that describes the beginning of the String
  4704.  
  4705.     \return
  4706.         const_reverse_iterator object that describes the beginning of the String (so is actually at the end)
  4707.     */
  4708.     const_reverse_iterator    rbegin(void) const
  4709.     {
  4710.         return const_reverse_iterator(end());
  4711.     }
  4712.  
  4713.     /*!
  4714.     \brief
  4715.         Return a reverse iterator that describes the end of the String
  4716.  
  4717.     \return
  4718.         reverse_iterator object that describes the end of the String (so is actually at the beginning)
  4719.     */
  4720.     reverse_iterator        rend(void)
  4721.     {
  4722.         return reverse_iterator(begin());
  4723.     }
  4724.  
  4725.     /*!
  4726.     \brief
  4727.         Return a constant reverse iterator that describes the end of the String
  4728.  
  4729.     \return
  4730.         const_reverse_iterator object that describes the end of the String (so is actually at the beginning)
  4731.     */
  4732.     const_reverse_iterator    rend(void) const
  4733.     {
  4734.         return const_reverse_iterator(begin());
  4735.     }
  4736.  
  4737. private:
  4738.     /*************************************************************************
  4739.         Implementation Functions
  4740.     *************************************************************************/
  4741.     // string management
  4742.  
  4743.     // change size of allocated buffer so it is at least 'new_size'.
  4744.     // May or may not cause re-allocation and copy of buffer if size is larger
  4745.     // will never re-allocate to make size smaller.  (see trim())
  4746.     bool    grow(size_type new_size);
  4747.  
  4748.     // perform re-allocation to remove wasted space.
  4749.     void    trim(void);
  4750.  
  4751.     // set the length of the string, and terminate it, according to the given value (will not re-allocate, use grow() first).
  4752.     void    setlen(size_type len)
  4753.     {
  4754.         d_cplength = len;
  4755.         ptr()[len] = (utf32)(0);
  4756.     }
  4757.  
  4758.     // return a ptr to the buffer in use.
  4759.     utf32*    ptr(void)
  4760.     {
  4761.         return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
  4762.     }
  4763.  
  4764.     // return a ptr tot he buffer in use (const version)
  4765.     const utf32*    ptr(void) const
  4766.     {
  4767.         return (d_reserve > STR_QUICKBUFF_SIZE) ? d_buffer : d_quickbuff;
  4768.     }
  4769.  
  4770.     // initialise string object
  4771.     void    init(void)
  4772.     {
  4773.         d_reserve            = STR_QUICKBUFF_SIZE;
  4774.         d_encodedbuff        = NULL;
  4775.         d_encodedbufflen    = 0;
  4776.         d_encodeddatlen        = 0;
  4777.         setlen(0);
  4778.     }
  4779.  
  4780.     // return true if the given pointer is inside the string data
  4781.     bool    inside(utf32* inptr)
  4782.     {
  4783.         if (inptr < ptr() || ptr() + d_cplength <= inptr)
  4784.             return false;
  4785.         else
  4786.             return true;
  4787.     }
  4788.  
  4789.     // compute distance between two iterators, returning a 'safe' value
  4790.     size_type safe_iter_dif(const const_iterator& iter1, const const_iterator& iter2) const
  4791.     {
  4792.         return (iter1.d_ptr == 0) ? 0 : (iter1 - iter2);
  4793.     }
  4794.     
  4795.     // encoding functions
  4796.     // for all:
  4797.     //    src_len is in code units, or 0 for null terminated string.
  4798.     //    dest_len is in code units.
  4799.     //    returns number of code units put into dest buffer.
  4800.     size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const
  4801.     {
  4802.         // count length for null terminated source...
  4803.         if (src_len == 0)
  4804.         {
  4805.             src_len = utf_length(src);
  4806.         }
  4807.  
  4808.         size_type destCapacity = dest_len;
  4809.  
  4810.         // while there is data in the source buffer,
  4811.         for (uint idx = 0; idx < src_len; ++idx)
  4812.         {
  4813.             utf32    cp = src[idx];
  4814.  
  4815.             // check there is enough destination buffer to receive this encoded unit (exit loop & return if not)
  4816.             if (destCapacity < encoded_size(cp))
  4817.             {
  4818.                 break;
  4819.             }
  4820.  
  4821.             if (cp < 0x80)
  4822.             {
  4823.                 *dest++ = (utf8)cp;
  4824.                 --destCapacity;
  4825.             }
  4826.             else if (cp < 0x0800)
  4827.             {
  4828.                 *dest++ = (utf8)((cp >> 6) | 0xC0);
  4829.                 *dest++ = (utf8)((cp & 0x3F) | 0x80);
  4830.                 destCapacity -= 2;
  4831.             }
  4832.             else if (cp < 0x10000)
  4833.             {
  4834.                 *dest++ = (utf8)((cp >> 12) | 0xE0);
  4835.                 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
  4836.                 *dest++ = (utf8)((cp & 0x3F) | 0x80);
  4837.                 destCapacity -= 3;
  4838.             }
  4839.             else
  4840.             {
  4841.                 *dest++ = (utf8)((cp >> 18) | 0xF0);
  4842.                 *dest++ = (utf8)(((cp >> 12) & 0x3F) | 0x80);
  4843.                 *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
  4844.                 *dest++ = (utf8)((cp & 0x3F) | 0x80);
  4845.                 destCapacity -= 4;
  4846.             }
  4847.  
  4848.         }
  4849.  
  4850.         return dest_len - destCapacity;
  4851.     }
  4852.  
  4853.     size_type encode(const utf8* src, utf32* dest, size_type dest_len, size_type src_len = 0) const
  4854.     {
  4855.         // count length for null terminated source...
  4856.         if (src_len == 0)
  4857.         {
  4858.             src_len = utf_length(src);
  4859.         }
  4860.  
  4861.         size_type destCapacity = dest_len;
  4862.  
  4863.         // while there is data in the source buffer, and space in the dest buffer
  4864.         for (uint idx = 0; ((idx < src_len) && (destCapacity > 0));)
  4865.         {
  4866.             utf32    cp;
  4867.             utf8    cu = src[idx++];
  4868.  
  4869.             if (cu < 0x80)
  4870.             {
  4871.                 cp = (utf32)(cu);
  4872.             }
  4873.             else if (cu < 0xE0)
  4874.             {
  4875.                 cp = ((cu & 0x1F) << 6);
  4876.                 cp |= (src[idx++] & 0x3F);
  4877.             }
  4878.             else if (cu < 0xF0)
  4879.             {
  4880.                 cp = ((cu & 0x0F) << 12);
  4881.                 cp |= ((src[idx++] & 0x3F) << 6);
  4882.                 cp |= (src[idx++] & 0x3F);
  4883.             }
  4884.             else
  4885.             {
  4886.                 cp = ((cu & 0x07) << 18);
  4887.                 cp |= ((src[idx++] & 0x3F) << 12);
  4888.                 cp |= ((src[idx++] & 0x3F) << 6);
  4889.                 cp |= (src[idx++] & 0x3F);
  4890.             }
  4891.  
  4892.             *dest++ = cp;
  4893.             --destCapacity;
  4894.         }
  4895.  
  4896.         return dest_len - destCapacity;
  4897.     }
  4898.  
  4899.     // return the number of utf8 code units required to encode the given utf32 code point
  4900.     size_type encoded_size(utf32 code_point) const
  4901.     {
  4902.         if (code_point < 0x80)
  4903.             return 1;
  4904.         else if (code_point < 0x0800)
  4905.             return 2;
  4906.         else if (code_point < 0x10000)
  4907.             return 3;
  4908.         else
  4909.             return 4;
  4910.     }
  4911.  
  4912.     // return number of code units required to re-encode given null-terminated utf32 data as utf8.  return does not include terminating null.
  4913.     size_type encoded_size(const utf32* buf) const
  4914.     {
  4915.         return encoded_size(buf, utf_length(buf));
  4916.     }
  4917.  
  4918.     // return number of code units required to re-encode given utf32 data as utf8.   len is number of code units in 'buf'.
  4919.     size_type encoded_size(const utf32* buf, size_type len) const
  4920.     {
  4921.         size_type count = 0;
  4922.  
  4923.         while (len--)
  4924.         {
  4925.             count += encoded_size(*buf++);
  4926.         }
  4927.  
  4928.         return count;
  4929.     }
  4930.  
  4931.     // return number of utf32 code units required to re-encode given utf8 data as utf32.  return does not include terminating null.
  4932.     size_type encoded_size(const utf8* buf) const
  4933.     {
  4934.         return encoded_size(buf, utf_length(buf));
  4935.     }
  4936.  
  4937.     // return number of utf32 code units required to re-encode given utf8 data as utf32.  len is number of code units in 'buf'.
  4938.     size_type encoded_size(const utf8* buf, size_type len) const
  4939.     {
  4940.         utf8 tcp;
  4941.         size_type count = 0;
  4942.  
  4943.         while (len--)
  4944.         {
  4945.             tcp = *buf++;
  4946.             ++count;
  4947.  
  4948.             if (tcp < 0x80)
  4949.             {
  4950.             }
  4951.             else if (tcp < 0xE0)
  4952.             {
  4953.                 --len;
  4954.                 ++buf;
  4955.             }
  4956.             else if (tcp < 0xF0)
  4957.             {
  4958.                 len -= 2;
  4959.                 buf += 2;
  4960.             }
  4961.             else
  4962.             {
  4963.                 len -= 2;
  4964.                 buf += 3;
  4965.             }
  4966.  
  4967.         }
  4968.  
  4969.         return count;
  4970.     }
  4971.  
  4972.     // return number of code units in a null terminated string
  4973.     size_type utf_length(const utf8* utf8_str) const
  4974.     {
  4975.         size_type cnt = 0;
  4976.         while (*utf8_str++)
  4977.             cnt++;
  4978.  
  4979.         return cnt;
  4980.     }
  4981.  
  4982.     // return number of code units in a null terminated string
  4983.     size_type utf_length(const utf32* utf32_str) const
  4984.     {
  4985.         size_type cnt = 0;
  4986.         while (*utf32_str++)
  4987.             cnt++;
  4988.  
  4989.         return cnt;
  4990.     }
  4991.  
  4992.     // build an internal buffer with the string encoded as utf8 (remains valid until string is modified).
  4993.     utf8* build_utf8_buff(void) const;
  4994.  
  4995.     // compare two utf32 buffers
  4996.     int    utf32_comp_utf32(const utf32* buf1, const utf32* buf2, size_type cp_count) const
  4997.     {
  4998.         if (!cp_count)
  4999.             return 0;
  5000.  
  5001.         while ((--cp_count) && (*buf1 == *buf2))
  5002.             buf1++, buf2++;
  5003.         
  5004.         return *buf1 - *buf2;
  5005.     }
  5006.  
  5007.     // compare utf32 buffer with char buffer (chars are taken to be code-points in the range 0x00-0xFF)
  5008.     int utf32_comp_char(const utf32* buf1, const char* buf2, size_type cp_count) const
  5009.     {
  5010.         if (!cp_count)
  5011.             return 0;
  5012.  
  5013.         while ((--cp_count) && (*buf1 == static_cast<utf32>(static_cast<unsigned char>(*buf2))))
  5014.             buf1++, buf2++;
  5015.  
  5016.         return *buf1 - static_cast<utf32>(static_cast<unsigned char>(*buf2));
  5017.     }
  5018.  
  5019.     // compare utf32 buffer with encoded utf8 data
  5020.     int utf32_comp_utf8(const utf32* buf1, const utf8* buf2, size_type cp_count) const
  5021.     {
  5022.         if (!cp_count)
  5023.             return 0;
  5024.  
  5025.         utf32    cp;
  5026.         utf8    cu;
  5027.  
  5028.         do
  5029.         {
  5030.             cu = *buf2++;
  5031.  
  5032.             if (cu < 0x80)
  5033.             {
  5034.                 cp = (utf32)(cu);
  5035.             }
  5036.             else if (cu < 0xE0)
  5037.             {
  5038.                 cp = ((cu & 0x1F) << 6);
  5039.                 cp |= (*buf2++ & 0x3F);
  5040.             }
  5041.             else if (cu < 0xF0)
  5042.             {
  5043.                 cp = ((cu & 0x0F) << 12);
  5044.                 cp |= ((*buf2++ & 0x3F) << 6);
  5045.                 cp |= (*buf2++ & 0x3F);
  5046.             }
  5047.             else
  5048.             {
  5049.                 cp = ((cu & 0x07) << 18);
  5050.                 cp |= ((*buf2++ & 0x3F) << 12);
  5051.                 cp |= ((*buf2++ & 0x3F) << 6);
  5052.                 cp |= (*buf2++ & 0x3F);
  5053.             }
  5054.  
  5055.         } while ((*buf1++ == cp) && (--cp_count));
  5056.  
  5057.         return (*--buf1) - cp;
  5058.     }
  5059.  
  5060.     // return index of first occurrence of 'code_point' in std::string 'str', or npos if none
  5061.     size_type find_codepoint(const std::string& str, utf32 code_point) const
  5062.     {
  5063.         size_type idx = 0, sze = (size_type)str.size();
  5064.  
  5065.         while (idx != sze)
  5066.         {
  5067.             if (code_point == static_cast<utf32>(static_cast<unsigned char>(str[idx])))
  5068.                 return idx;
  5069.  
  5070.             ++idx;
  5071.         }
  5072.  
  5073.         return npos;
  5074.     }
  5075.  
  5076.     // return index of first occurrence of 'code_point' in utf8 encoded string 'str', or npos if none.  len is in code points.
  5077.     size_type find_codepoint(const utf8* str, size_type len, utf32 code_point) const 
  5078.     {
  5079.         size_type idx = 0;
  5080.  
  5081.         utf32    cp;
  5082.         utf8    cu;
  5083.  
  5084.         while (idx != len) {
  5085.             cu = *str++;
  5086.  
  5087.             if (cu < 0x80)
  5088.             {
  5089.                 cp = (utf32)(cu);
  5090.             }
  5091.             else if (cu < 0xE0)
  5092.             {
  5093.                 cp = ((cu & 0x1F) << 6);
  5094.                 cp |= (*str++ & 0x3F);
  5095.             }
  5096.             else if (cu < 0xF0)
  5097.             {
  5098.                 cp = ((cu & 0x0F) << 12);
  5099.                 cp |= ((*str++ & 0x3F) << 6);
  5100.                 cp |= (*str++ & 0x3F);
  5101.             }
  5102.             else
  5103.             {
  5104.                 cp = ((cu & 0x07) << 18);
  5105.                 cp |= ((*str++ & 0x3F) << 12);
  5106.                 cp |= ((*str++ & 0x3F) << 6);
  5107.                 cp |= (*str++ & 0x3F);
  5108.             }
  5109.  
  5110.             if (code_point == cp)
  5111.                 return idx;
  5112.  
  5113.             ++idx;
  5114.         }
  5115.  
  5116.         return npos;
  5117.     }
  5118.  
  5119.  
  5120.     // return index of first occurrence of 'code_point' in char array 'chars', or npos if none
  5121.     size_type find_codepoint(const char* chars, size_type chars_len, utf32 code_point) const
  5122.     {
  5123.         for (size_type idx = 0; idx != chars_len; ++idx)
  5124.         {
  5125.             if (code_point == static_cast<utf32>(static_cast<unsigned char>(chars[idx])))
  5126.                 return idx;
  5127.         }
  5128.  
  5129.         return npos;
  5130.     }
  5131.  
  5132. };
  5133.  
  5134.  
  5135. //////////////////////////////////////////////////////////////////////////
  5136. // Comparison operators
  5137. //////////////////////////////////////////////////////////////////////////
  5138. /*!
  5139. \brief
  5140.     Return true if String \a str1 is equal to String \a str2
  5141. */
  5142. bool CEGUIEXPORT    operator==(const String& str1, const String& str2);
  5143.  
  5144. /*!
  5145. \brief
  5146.     Return true if String \a str is equal to std::string \a std_str
  5147. */
  5148. bool CEGUIEXPORT    operator==(const String& str, const std::string& std_str);
  5149.  
  5150. /*!
  5151. \brief
  5152.     Return true if String \a str is equal to std::string \a std_str
  5153. */
  5154. bool CEGUIEXPORT    operator==(const std::string& std_str, const String& str);
  5155.  
  5156. /*!
  5157. \brief
  5158.     Return true if String \a str is equal to null-terminated utf8 data \a utf8_str
  5159. */
  5160. bool CEGUIEXPORT    operator==(const String& str, const utf8* utf8_str);
  5161.  
  5162. /*!
  5163. \brief
  5164.     Return true if String \a str is equal to null-terminated utf8 data \a utf8_str
  5165. */
  5166. bool CEGUIEXPORT    operator==(const utf8* utf8_str, const String& str);
  5167.  
  5168. /*!
  5169. \brief
  5170.     Return true if String \a str1 is not equal to String \a str2
  5171. */
  5172. bool CEGUIEXPORT    operator!=(const String& str1, const String& str2);
  5173.  
  5174. /*!
  5175. \brief
  5176.     Return true if String \a str is not equal to std::string \a std_str
  5177. */
  5178. bool CEGUIEXPORT    operator!=(const String& str, const std::string& std_str);
  5179.  
  5180. /*!
  5181. \brief
  5182.     Return true if String \a str is not equal to std::string \a std_str
  5183. */
  5184. bool CEGUIEXPORT    operator!=(const std::string& std_str, const String& str);
  5185.  
  5186. /*!
  5187. \brief
  5188.     Return true if String \a str is not equal to null-terminated utf8 data \a utf8_str
  5189. */
  5190. bool CEGUIEXPORT    operator!=(const String& str, const utf8* utf8_str);
  5191.  
  5192. /*!
  5193. \brief
  5194.     Return true if String \a str is not equal to null-terminated utf8 data \a utf8_str
  5195. */
  5196. bool CEGUIEXPORT    operator!=(const utf8* utf8_str, const String& str);
  5197.  
  5198. /*!
  5199. \brief
  5200.     Return true if String \a str1 is lexicographically less than String \a str2
  5201. */
  5202. bool CEGUIEXPORT    operator<(const String& str1, const String& str2);
  5203.  
  5204. /*!
  5205. \brief
  5206.     Return true if String \a str is lexicographically less than std::string \a std_str
  5207. */
  5208. bool CEGUIEXPORT    operator<(const String& str, const std::string& std_str);
  5209.  
  5210. /*!
  5211. \brief
  5212.     Return true if String \a str is lexicographically less than std::string \a std_str
  5213. */
  5214. bool CEGUIEXPORT    operator<(const std::string& std_str, const String& str);
  5215.  
  5216. /*!
  5217. \brief
  5218.     Return true if String \a str is lexicographically less than null-terminated utf8 data \a utf8_str
  5219. */
  5220. bool CEGUIEXPORT    operator<(const String& str, const utf8* utf8_str);
  5221.  
  5222. /*!
  5223. \brief
  5224.     Return true if String \a str is lexicographically less than null-terminated utf8 data \a utf8_str
  5225. */
  5226. bool CEGUIEXPORT    operator<(const utf8* utf8_str, const String& str);
  5227.  
  5228. /*!
  5229. \brief
  5230.     Return true if String \a str1 is lexicographically greater than String \a str2
  5231. */
  5232. bool CEGUIEXPORT    operator>(const String& str1, const String& str2);
  5233.  
  5234. /*!
  5235. \brief
  5236.     Return true if String \a str is lexicographically greater than std::string \a std_str
  5237. */
  5238. bool CEGUIEXPORT    operator>(const String& str, const std::string& std_str);
  5239.  
  5240. /*!
  5241. \brief
  5242.     Return true if String \a str is lexicographically greater than std::string \a std_str
  5243. */
  5244. bool CEGUIEXPORT    operator>(const std::string& std_str, const String& str);
  5245.  
  5246. /*!
  5247. \brief
  5248.     Return true if String \a str is lexicographically greater than null-terminated utf8 data \a utf8_str
  5249. */
  5250. bool CEGUIEXPORT    operator>(const String& str, const utf8* utf8_str);
  5251.  
  5252. /*!
  5253. \brief
  5254.     Return true if String \a str is lexicographically greater than null-terminated utf8 data \a utf8_str
  5255. */
  5256. bool CEGUIEXPORT    operator>(const utf8* utf8_str, const String& str);
  5257.  
  5258. /*!
  5259. \brief
  5260.     Return true if String \a str1 is lexicographically less than or equal to String \a str2
  5261. */
  5262. bool CEGUIEXPORT    operator<=(const String& str1, const String& str2);
  5263.  
  5264. /*!
  5265. \brief
  5266.     Return true if String \a str is lexicographically less than or equal to std::string \a std_str
  5267. */
  5268. bool CEGUIEXPORT    operator<=(const String& str, const std::string& std_str);
  5269.  
  5270. /*!
  5271. \brief
  5272.     Return true if String \a str is lexicographically less than or equal to std::string \a std_str
  5273. */
  5274. bool CEGUIEXPORT    operator<=(const std::string& std_str, const String& str);
  5275.  
  5276. /*!
  5277. \brief
  5278.     Return true if String \a str is lexicographically less than or equal to null-terminated utf8 data \a utf8_str
  5279. */
  5280. bool CEGUIEXPORT    operator<=(const String& str, const utf8* utf8_str);
  5281.  
  5282. /*!
  5283. \brief
  5284.     Return true if String \a str is lexicographically less than or equal to null-terminated utf8 data \a utf8_str
  5285. */
  5286. bool CEGUIEXPORT    operator<=(const utf8* utf8_str, const String& str);
  5287.  
  5288. /*!
  5289. \brief
  5290.     Return true if String \a str1 is lexicographically greater than or equal to String \a str2
  5291. */
  5292. bool CEGUIEXPORT    operator>=(const String& str1, const String& str2);
  5293.  
  5294. /*!
  5295. \brief
  5296.     Return true if String \a str is lexicographically greater than or equal to std::string \a std_str
  5297. */
  5298. bool CEGUIEXPORT    operator>=(const String& str, const std::string& std_str);
  5299.  
  5300. /*!
  5301. \brief
  5302.     Return true if String \a str is lexicographically greater than or equal to std::string \a std_str
  5303. */
  5304. bool CEGUIEXPORT    operator>=(const std::string& std_str, const String& str);
  5305.  
  5306. /*!
  5307. \brief
  5308.     Return true if String \a str is lexicographically greater than or equal to null-terminated utf8 data \a utf8_str
  5309. */
  5310. bool CEGUIEXPORT    operator>=(const String& str, const utf8* utf8_str);
  5311.  
  5312. /*!
  5313. \brief
  5314.     Return true if String \a str is lexicographically greater than or equal to null-terminated utf8 data \a utf8_str
  5315. */
  5316. bool CEGUIEXPORT    operator>=(const utf8* utf8_str, const String& str);
  5317.  
  5318. /*!
  5319. \brief
  5320.     Return true if String \a str is equal to c-string \a c_str
  5321. */
  5322. bool CEGUIEXPORT    operator==(const String& str, const char* c_str);
  5323.  
  5324. /*!
  5325. \brief
  5326.     Return true if c-string \a c_str is equal to String \a str
  5327. */
  5328. bool CEGUIEXPORT    operator==(const char* c_str, const String& str);
  5329.  
  5330. /*!
  5331. \brief
  5332.     Return true if String \a str is not equal to c-string \a c_str
  5333. */
  5334. bool CEGUIEXPORT    operator!=(const String& str, const char* c_str);
  5335.  
  5336. /*!
  5337. \brief
  5338.     Return true if c-string \a c_str is not equal to String \a str
  5339. */
  5340. bool CEGUIEXPORT    operator!=(const char* c_str, const String& str);
  5341.  
  5342. /*!
  5343. \brief
  5344.     Return true if String \a str is lexicographically less than c-string \a c_str
  5345. */
  5346. bool CEGUIEXPORT    operator<(const String& str, const char* c_str);
  5347.  
  5348. /*!
  5349. \brief
  5350.     Return true if c-string \a c_str is lexicographically less than String \a str
  5351. */
  5352. bool CEGUIEXPORT    operator<(const char* c_str, const String& str);
  5353.  
  5354. /*!
  5355. \brief
  5356. Return true if String \a str is lexicographically greater than c-string \a c_str
  5357. */
  5358. bool CEGUIEXPORT    operator>(const String& str, const char* c_str);
  5359.  
  5360. /*!
  5361. \brief
  5362. Return true if c-string \a c_str is lexicographically greater than String \a str
  5363. */
  5364. bool CEGUIEXPORT    operator>(const char* c_str, const String& str);
  5365.  
  5366. /*!
  5367. \brief
  5368.     Return true if String \a str is lexicographically less than or equal to c-string \a c_str
  5369. */
  5370. bool CEGUIEXPORT    operator<=(const String& str, const char* c_str);
  5371.  
  5372. /*!
  5373. \brief
  5374.     Return true if c-string \a c_str is lexicographically less than or equal to String \a str
  5375. */
  5376. bool CEGUIEXPORT    operator<=(const char* c_str, const String& str);
  5377.  
  5378. /*!
  5379. \brief
  5380.     Return true if String \a str is lexicographically greater than or equal to c-string \a c_str
  5381. */
  5382. bool CEGUIEXPORT    operator>=(const String& str, const char* c_str);
  5383.  
  5384. /*!
  5385. \brief
  5386.     Return true if c-string \a c_str is lexicographically greater than or equal to String \a str
  5387. */
  5388. bool CEGUIEXPORT    operator>=(const char* c_str, const String& str);
  5389.  
  5390. //////////////////////////////////////////////////////////////////////////
  5391. // Concatenation operator functions
  5392. //////////////////////////////////////////////////////////////////////////
  5393. /*!
  5394. \brief
  5395.     Return String object that is the concatenation of the given inputs
  5396.  
  5397. \param str1
  5398.     String object describing first part of the new string
  5399.  
  5400. \param str2
  5401.     String object describing the second part of the new string
  5402.  
  5403. \return
  5404.     A String object that is the concatenation of \a str1 and \a str2
  5405.  
  5406. \exception std::length_error    Thrown if the resulting String would be too large.
  5407. */
  5408. String CEGUIEXPORT    operator+(const String& str1, const String& str2);
  5409.  
  5410. /*!
  5411. \brief
  5412.     Return String object that is the concatenation of the given inputs
  5413.  
  5414. \param str
  5415.     String object describing first part of the new string
  5416.  
  5417. \param std_str
  5418.     std::string object describing the second part of the new string
  5419.  
  5420. \return
  5421.     A String object that is the concatenation of \a str and \a std_str
  5422.  
  5423. \exception std::length_error    Thrown if the resulting String would be too large.
  5424. */
  5425. String CEGUIEXPORT    operator+(const String& str, const std::string& std_str);
  5426.  
  5427. /*!
  5428. \brief
  5429.     Return String object that is the concatenation of the given inputs
  5430.  
  5431. \param std_str
  5432.     std::string object describing the first part of the new string
  5433.  
  5434. \param str
  5435.     String object describing the second part of the new string
  5436.  
  5437. \return
  5438.     A String object that is the concatenation of \a std_str and \a str
  5439.  
  5440. \exception std::length_error    Thrown if the resulting String would be too large.
  5441. */
  5442. String CEGUIEXPORT    operator+(const std::string& std_str, const String& str);
  5443.  
  5444. /*!
  5445. \brief
  5446.     Return String object that is the concatenation of the given inputs
  5447.  
  5448. \param str
  5449.     String object describing first part of the new string
  5450.  
  5451. \param utf8_str
  5452.     Buffer containing null-terminated utf8 encoded data describing the second part of the new string
  5453.  
  5454. \return
  5455.     A String object that is the concatenation of \a str and \a utf8_str
  5456.  
  5457. \exception std::length_error    Thrown if the resulting String would be too large.
  5458. */
  5459. String CEGUIEXPORT    operator+(const String& str, const utf8* utf8_str);
  5460.  
  5461. /*!
  5462. \brief
  5463.     Return String object that is the concatenation of the given inputs
  5464.  
  5465. \param utf8_str
  5466.     Buffer containing null-terminated utf8 encoded data describing the first part of the new string
  5467.  
  5468. \param str
  5469.     String object describing the second part of the new string
  5470.  
  5471. \return
  5472.     A String object that is the concatenation of \a str and \a utf8_str
  5473.  
  5474. \exception std::length_error    Thrown if the resulting String would be too large.
  5475. */
  5476. String CEGUIEXPORT    operator+(const utf8* utf8_str, const String& str);
  5477.  
  5478. /*!
  5479. \brief
  5480.     Return String object that is the concatenation of the given inputs
  5481.  
  5482. \param str
  5483.     String object describing the first part of the new string
  5484.  
  5485. \param code_point
  5486.     utf32 code point describing the second part of the new string
  5487.  
  5488. \return
  5489.     A String object that is the concatenation of \a str and \a code_point
  5490.  
  5491. \exception std::length_error    Thrown if the resulting String would be too large.
  5492. */
  5493. String CEGUIEXPORT    operator+(const String& str, utf32 code_point);
  5494.  
  5495. /*!
  5496. \brief
  5497.     Return String object that is the concatenation of the given inputs
  5498.  
  5499. \param code_point
  5500.     utf32 code point describing the first part of the new string
  5501.  
  5502. \param str
  5503.     String object describing the second part of the new string
  5504.  
  5505. \return
  5506.     A String object that is the concatenation of \a code_point and \a str
  5507.  
  5508. \exception std::length_error    Thrown if the resulting String would be too large.
  5509. */
  5510. String CEGUIEXPORT    operator+(utf32 code_point, const String& str);
  5511.  
  5512. /*!
  5513. \brief
  5514.     Return String object that is the concatenation of the given inputs
  5515.  
  5516. \param str
  5517.     String object describing first part of the new string
  5518.  
  5519. \param c_str
  5520.     c-string describing the second part of the new string
  5521.  
  5522. \return
  5523.     A String object that is the concatenation of \a str and \a c_str
  5524.  
  5525. \exception std::length_error    Thrown if the resulting String would be too large.
  5526. */
  5527. String CEGUIEXPORT    operator+(const String& str, const char* c_str);
  5528.  
  5529. /*!
  5530. \brief
  5531.     Return String object that is the concatenation of the given inputs
  5532.  
  5533. \param c_str
  5534.     c-string describing the first part of the new string
  5535.  
  5536. \param str
  5537.     String object describing the second part of the new string
  5538.  
  5539. \return
  5540.     A String object that is the concatenation of \a c_str and \a str
  5541.  
  5542. \exception std::length_error    Thrown if the resulting String would be too large.
  5543. */
  5544. String CEGUIEXPORT    operator+(const char* c_str, const String& str);
  5545.  
  5546.  
  5547. //////////////////////////////////////////////////////////////////////////
  5548. // Output (stream) functions
  5549. //////////////////////////////////////////////////////////////////////////
  5550. CEGUIEXPORT std::ostream& operator<<(std::ostream& s, const String& str);
  5551.  
  5552.  
  5553. //////////////////////////////////////////////////////////////////////////
  5554. // Modifying operations
  5555. //////////////////////////////////////////////////////////////////////////
  5556. /*!
  5557. \brief
  5558.     Swap the contents for two String objects
  5559.  
  5560. \param str1
  5561.     String object who's contents are to be swapped with \a str2
  5562.  
  5563. \param str2
  5564.     String object who's contents are to be swapped with \a str1
  5565.  
  5566. \return
  5567.     Nothing
  5568. */
  5569. void CEGUIEXPORT swap(String& str1, String& str2);
  5570.  
  5571.  
  5572. } // End of  CEGUI namespace section
  5573.  
  5574.  
  5575. #endif    // end of guard _CEGUIString_h_
  5576.